首页 > 代码库 > Xitrum学习笔记23 - HOWTO

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()

 

Xitrum学习笔记23 - HOWTO