如果我正确理解了这个问题,您想从请求标头中提取用户 ID。我不确定过滤器是否是实现此目的的好地方。这可以通过不同的方式完成,我为此选择了 ActionBuilder 和 ActionTransformers。请参阅Play Framework 网站上的动作组合。
首先,您需要一个 RedirectingAction。然后我通过 TokenExtractAction 提取令牌,通过 UserIdExtractAction 提取用户 ID,并在 PermissionCheckAction 中检查 auth。
通过这种方式,它是可组合的、高性能的和可重用的。在您的控制器中,使用 SecureAction 而不是 Action。然后你就可以免费获得所有的奖励 userId、token 等。如果身份验证失败,它会默默地失败,不会弄乱你的控制器。这是基于我记得在 Play 网站上看到的示例。但我不得不延长它。在那提供的替代方案中,我发现这个对于验证每个 REST 请求情况最有用。
另外我正在使用actorsystem进行身份验证。您可以轻松地为自己构建一个。
case class RedirectingAction @Inject()(parser: BodyParsers.Default)(implicit val executionContext: ExecutionContext)
extends ActionBuilder[Request, AnyContent] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
block(request)
}
}
case class TokenExtractAction @Inject()(parser: BodyParsers.Default)(
implicit val executionContext: ExecutionContext)
extends ActionTransformer[Request, TokenExtractRequest] {
def transform[A](request: Request[A]): Future[TokenExtractRequest[A]] = Future.successful {
val token = request.headers.get(Conf.REST_AUTH_HEADER)
new TokenExtractRequest(token, Some(TokenTool.decodeToken(token.getOrElse("invalid_token")).plaintext), request)
}
}
case class UserIdExtractAction @Inject()(parser: BodyParsers.Default)(implicit val executionContext: ExecutionContext)
extends ActionTransformer[TokenExtractRequest, UserRequest] {
def transform[A](request: TokenExtractRequest[A]): Future[UserRequest[A]] = Future.successful {
new UserRequest(
userAuthRole = TokenTool.tokenGetRoleFromToken(request.token),
userId = TokenTool.tokenGetIdFromToken(request.token),
token = request.token,
plainTextToken = request.plainTextToken,
request = request
)
}
}
case class PermissionCheckActionIndividual @Inject()(authSystem: AuthSystem)(implicit val executionContext: ExecutionContext)
extends ActionFilter[UserRequest] {
implicit val timeout: akka.util.Timeout = 5.seconds
def filter[A](input: UserRequest[A]): Future[Option[Result]] = {
val token = input.headers.get(Conf.REST_AUTH_HEADER).orElse(Some("invalid token"))
val authorizer: ActorRef = authSystem.authorizer
// verify sig and check user validity
val res = authorizer ? CheckUserValidityFromToken(token)
res.flatMap {
case true =>
Future(None)
case false =>
Future(Some(Forbidden("Not permitted")))
}
}
}
class SecureActionProvider @Inject()(val authSystem: AuthSystem, val authService: AuthService)(implicit ec: ExecutionContext,
parser: BodyParsers.Default) {
def SecureAction: ActionBuilder[UserRequest, AnyContent] =
RedirectingAction(parser) andThen TokenExtractAction(parser) andThen UserIdExtractAction(parser) andThen PermissionCheckActionIndividual(
authSystem)
}
在您的控制器中:
def someSecureMethod = secureActionProvider.SecureAction.async ... {
...
}
希望这可以帮助。