与大多数关于Action组合的讨论(例如this one)不同,我需要在Action中解析传入的JSON请求。这是因为我们的应用程序提供了嵌入在JSON中的安全令牌(不是典型的标题中的。)
我想要实现的目标是:
object AuthenticatedAction extends ActionBuilder[UserRequest] with ActionTransformer[Request, UserRequest] {
// Do something magical here that will:
// 1. parse the inbound request.body.validate[GPToken]
// 2. (do stuff with the token to check authorization)
// 3. if NOT authorized return an HTTP NOTAUTHORIZED or FORBIDDEN
// 4. otherwise, forward the request to the desired endpoint
}
object SomeController extends Controller
val action = AuthenticatedAction(parse.json) { implicit request =>
request.body.validate[SomeRequest] match {
// Do whatever... totally transparent and already authorized
}
}
...
入站JSON将始终具有令牌,例如:
{
"token":"af75e4ad7564cfde",
// other parameters we don't care about
}
所以,我正在考虑解析只是想要我们想要(并且不最终解析复杂的,深层嵌套的JSON结构)我可能只有一个GPToken对象:
class GPToken(token: String)
object GPToken { implicit val readsToken = Json.reads[GPToken] }
然后在"魔法" AuthenticationAction我可以只对令牌进行反序列化,用数据库来检查授权,然后传递请求或发回NOTAUTHORIZED。但这就是我迷路的地方......我如何获取json正文,解析它,并通过我的安全层过滤所有传入的请求?
答案 0 :(得分:1)
我认为最好将该令牌移到您的请求标头中。这样做将允许您使用Play的AuthententicatedBuilder(ActionBuilder)来帮助进行身份验证。
如果你能做到这一点,那么你就可以有这样的特征:
trait Authentication {
object Authenticated extends play.api.mvc.Security.AuthenticatedBuilder(checkGPToken(_), onUnauthorized(_))
def checkGPToken(request: RequestHeader): Option[User] = {
request.headers.get("GPToken") flatMap { token =>
// Do the check with the token
// Return something about the user that will be available inside your actions
}
}
def onUnauthorized(request: RequestHeader) = {
// Do something when it doesn't pass authorization
Results.Unauthorized
}
}
现在使用您的控制器,您可以非常简单地创建一个需要身份验证的操作。
object SomeController extends Controller with Authentication {
def someAction = Authenticated { req =>
// Your user your header check is available
val user = req.user
// Do something in the context of being authenticated
Ok
}
}