Xitrum学习笔记23 - HOWTO
1. HTTP基本认证(Basic Authentication)
使用HTTP基本认证可以保护整个站点或是特定的action。
Xitrum不支持摘要认证(Digest Authentication),因为它容易受到中间人攻击(man-in-the-middle attack)。更好的安全机制,要使用Xitrum内建支持的HTTPS。
为整个站点配置HTTP基本认证:
在 config/xitrum.conf:
"basicAuth": { "realm": "xitrum", "username": "xitrum", "password": "xitrum" }
为某个Action配置HTTP基本认证:
import xitrum.Action class MyAction extends Action { beforeFilter { basicAuth("Realm") { (username, password) => username == "username" && password == "password" } } }
2. 加载配置文件
JSON文件
把自定义的配置文件保存在config路径下,这个路径会被放在开发环境和生产环境的classpath中。
开发环境的classpath配置由build.sbt设置,生产环境的classpath配置由script/runner设置
在Action中加载一个配置文件,如myconfig.json:
import xitrum.util.Loader case class MyConfig(username: String, password: String, children: Seq[String]) val myConfig = Loader.jsonFromClasspath[MyConfig]("myconfig.json")
myconfig.json:
{ "username": "God", "password": "Does God need a password?", "children": ["Adam", "Eva"] }
注意:key和字符串必须被双引号扩起;不能再JSON文件中写注释
属性文件(properties files)
也可以使用属性文件,但是它不是类型安全的,也不支持UTF-8和嵌套结构,还是JSON更好用一些。
myconfig.properties:
username = God password = Does God need a password? children = Adam, Eva
加载properties文件
import xitrum.util.Loader // Here you get an instance of java.util.Properties val properties = Loader.propertiesFromClasspath("myconfig.properties")
类型安全的配置文件
可以使用https://github.com/typesafehub/config提供的配置文件库来加载配置文件,是一种更好的加载方式。
这个库的sbt dependency:
libraryDependencies += "com.typesafe" % "config" % "1.3.1"
myconfig.conf:
username = God password = Does God need a password? children = ["Adam", "Eva"]
加载文件
import com.typesafe.config.{Config, ConfigFactory} val config = ConfigFactory.load("myconfig.conf") val username = config.getString("username") val password = config.getString("password") val children = config.getStringList("children")
3. 序列化和反序列化
序列化成Array[Byte]:
import xitrum.util.SeriDeseri val bytes = SeriDeseri.toBytes("my serializable object")
从Array[Byte]反序列化:
val option = SeriDeseri.fromBytes[MyType](bytes) // Option[MyType]
保存到文件里:
import xitrum.util.Loader Loader.bytesToFile(bytes, "myObject.bin")
从文件中加载:
val bytes = Loader.bytesFromFile("myObject.bin")
4. 加密数据
如果加密数据后不需解密,可以使用MD5
如果要解密数据,可以使用Xitrum提供的工具类
import xitrum.util.Secure // Array[Byte] val encrypted = Secure.encrypt("my data".getBytes) // Option[Array[Byte]] val decrypted = Secure.decrypt(encrypted)
可以使用xitrum.util.UrlSafeBase64编码和解码二进制数据成普通字符串(嵌入HTML)
// String that can be included in URL, cookie etc. val string = UrlSafeBase64.noPaddingEncode(encrypted) // Option[Array[Byte]] val encrypted2 = UrlSafeBase64.autoPaddingDecode(string)
将以上步骤合并为一步
import xitrum.util.SeriDeseri val mySerializableObject = new MySerializableClass // String val encrypted = SeriDeseri.toSecureUrlSafeBase64(mySerializableObject) // Option[MySerializableClass] val decrypted = SeriDeseri.fromSecureUrlSafeBase64[MySerializableClass](encrypted)
SeriDeseri使用Twitter Chill进行序列化和反序列化,数据必须是可以序列化的
可以为加密指定key
val encrypted = Secure.encrypt("my data".getBytes, "my key") val decrypted = Secure.decrypt(encrypted, "my key") val encrypted = SeriDeseri.toSecureUrlSafeBase64(mySerializableObject, "my key") val decrypted = SeriDeseri.fromSecureUrlSafeBase64[MySerializableClass](encrypted, "my key")
如果没有指定key,xitrum.conf中指定的secureKey值会被当做key使用。
5. 以相同的域名运行多个站点
如果想使用反向代理(如Nginx)以相同的域名运行多个站点
http://example.com/site1/... http://example.com/site2/...
可以在config/xitrum.conf中配置baseUrl
在JS代码中,使用xitrum.js中的withBaseUrl为Ajax请求获取正确的URLs
# If the current site's baseUrl is "site1", the result will be: # /site1/path/to/my/action xitrum.withBaseUrl('/path/to/my/action')
6. 把Markdown文本转换成HTML
如果已经配置了项目使用Scalate模板引擎,只需要使用以下方法
import org.fusesource.scalamd.Markdown val html = Markdown("input")
否则,还需要在build.sbt中加入依赖
libraryDependencies += "org.fusesource.scalamd" %% "scalamd" % "1.6"
7. 监控文件变更
可以为java.nio.file.Class StandardWatchEventKinds在监控文件和路径注册回调方法
import java.nio.file.Paths import xitrum.util.FileMonitor val target = Paths.get("absolute_path_or_path_relative_to_application_directory").toAbsolutePath FileMonitor.monitor(FileMonitor.MODIFY, target, { path => // Do some callback with path println(s"File modified: $path") // And stop monitoring if necessary FileMonitor.unmonitor(FileMonitor.MODIFY, target) })
在底层, FileMonitor 使用了 Schwatcher(https://github.com/lloydmeta/schwatcher)
8. 临时路径
Xitrum项目默认使用在当前的工作路径下的tmp路径来保存Scalate生成的.scala文件和大的上传文件。
要获取这个路径,使用
xitrum.Config.xitrum.tmpDir.getAbsolutePath
要在临时路径下创建文件或路径:
val file = new java.io.File(xitrum.Config.xitrum.tmpDir, "myfile") val dir = new java.io.File(xitrum.Config.xitrum.tmpDir, "mydir") dir.mkdirs()