【问题标题】:Custom Action composition to authorize based on JSON token in Play (Scala)在 Play (Scala) 中基于 JSON 令牌进行授权的自定义操作组合
【发布时间】:2015-05-17 11:32:41
【问题描述】:

与大多数关于 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 正文,解析它,并通过我的安全层过滤所有传入的请求?

【问题讨论】:

  • 注意一个骗局,但非常非常接近。在这种情况下,我们需要解释入站 JSON(而不是请求标头),而我在这样做时遇到了麻烦。引用的文章讨论了使用标头。

标签: json scala playframework


【解决方案1】:

我认为最好将该令牌移动到您的请求标头中。这样做将允许您使用 Play 的 AuthenticatedBuilder,它是一个帮助身份验证的 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
    }
}

【讨论】:

  • 我同意,这更有意义。不幸的是,我们现有的应用程序将安全令牌嵌入到所有 JSON 请求中(作为第一个元素,名为“令牌”)。我知道这很奇怪,但就是这样......
猜你喜欢
  • 1970-01-01
  • 2014-11-08
  • 2016-06-09
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2015-07-15
相关资源
最近更新 更多