Аутентифицированный маршрут может быть достигнут с использованием композиции действия .Вот один пример, взятый из playframework / play-scala-secure-session-example , который использует ActionBuilder
для реализации аутентификации через UserInfoAction.invokeBlock
:
override def invokeBlock[A](request: Request[A], block: (UserRequest[A]) => Future[Result]): Future[Result] = {
// deal with the options first, then move to the futures
val maybeFutureResult: Option[Future[Result]] = for {
sessionId <- request.session.get(SESSION_ID)
userInfoCookie <- request.cookies.get(USER_INFO_COOKIE_NAME)
} yield {
// Future can be flatmapped here and squished with a partial function
sessionService.lookup(sessionId).flatMap {
case Some(secretKey) =>
val cookieBaker = factory.createCookieBaker(secretKey)
val maybeUserInfo = cookieBaker.decodeFromCookie(Some(userInfoCookie))
block(new UserRequest[A](request, maybeUserInfo, messagesApi))
case None =>
// We've got a user with a client session id, but no server-side state.
// Let's redirect them back to the home page without any session cookie stuff.
Future.successful {
discardingSession {
Redirect(routes.HomeController.index())
}.flashing(FLASH_ERROR -> "Your session has expired!")
}
}
}
maybeFutureResult.getOrElse {
block(new UserRequest[A](request, None, messagesApi))
}
}
Если аутентификация завершается успешно, запрос обогащается maybeUserInfo
, а если он не проходит, происходит перенаправление с Your session has expired
, добавляемым во флэш-память.Теперь, чтобы добавить аутентификацию в маршрут, просто введите UserInfoAction
в контроллер и назовите его примерно так:
def login = userAction.async { implicit request: UserRequest[AnyContent] =>
...
// request.userInfo is now available
}