【发布时间】:2016-03-28 08:10:44
【问题描述】:
我正在尝试创建一个自定义指令,以后可以使用它来验证用户角色,如下所示:
val route = put & authorize(ADMIN) {
// do sth
}
或
val route = put {
authorize(ADMIN) {
//do sth
}
}
。这是我到目前为止得到的:
def authorize(role: String): Directive0 = {
extractToken { t: String =>
validateToken(t) {
extractRoles(t) { roles: Seq[String] =>
validate(roles.contains(role), s"User does not have the required role")
}
}
}
}
def extractRoles(token: String): Directive1[Seq[String]] = {
token match {
case JsonWebToken(header, claimsSet, signature) => {
val decoded = decodeJWT(token)
decoded match {
case Some(_) => provide(extractRoleCodesFromJWT(decoded.get))
case None => provide(Seq())
}
}
case x =>
provide(Seq())
}
}
def validateToken(token: String): Directive0 = validate(validateJWT(token), INVALID_TOKEN_MESSAGE)
def extractToken: Directive1[Option[String]] = extractToken | extractHeader
def extractCookie: Directive1[Option[String]] = optionalCookie(JWT_COOKIE_NAME).map(_.map(_.value))
def extractHeader: Directive1[Option[String]] = optionalHeaderValueByName(JWT_HEADER_NAME)
除了我想稍后使用的实际 Directive0(授权)之外,所有编译都很好。最里面的行validate(...) 显示编译错误,提示“server.Directive0 类型的表达式不符合预期的 server.Route 类型”
如何正确嵌套其他指令以形成我的授权指令? 或者我可以以其他方式连接它们,而不是嵌套? 不幸的是,关于自定义指令的文档非常少。
[更新]
感谢 Java Anto 的指针,这就是我想出的。
def authorize(role: String): Directive0 = {
extractToken.flatMap(validateToken)
.flatMap(extractRoles)
.flatMap(roles => validate(roles.contains(role), MISSING_ROLE_MESSAGE))
}
这可以编译,并有望完成我正确测试它的技巧。
【问题讨论】:
-
您可以使用现有指令上的'map'和'flatMap'函数来组成新的指令。
-
@Java Anto:谢谢,这是一个很好的指导。我还不能回答自己,所以我会更新问题以包含解决方案。
-
很高兴它有帮助!对于清晰的文档,我建议您查看spray website
-
@Thelonius 有用吗?我同意这方面的 Spray 文档(仍然)不足。