scala - 相当于 akka-http 中经过身份验证的路由?
问题描述
这可能是一个菜鸟问题,因为我只是从游戏开始。我们可以在 akka-http 中找到的经过身份验证的路由的等价物是什么?下面是使用 akka-http 的经过身份验证的路由示例
def oauth2Authenticator(credentials: Credentials): Future[Option[ScalaFirebaseToken]] = {
credentials match {
case p @ Credentials.Provided(token) =>
ImportFirebaseCredentials.decodeToken(token).flatMap {
case token : FirebaseToken => {
Future(Some(
ScalaFirebaseToken(token.getUid,
Option(token.getEmail),
Option(token.getName),
Option(token.getPicture)
)))
}
case _ => Future.successful(None)
}
case _ =>
println("couldn't obtain credentials")
Future.successful(None)
}
}
def authenticated = authenticateOAuth2Async("auth", oauth2Authenticator)
val route =
path("user") {
(get & authenticated) { authResult =>
complete(getUserByUid(authResult.uid, authResult.email, authResult.name))
}
}
此代码从请求标头中获取凭据,根据 firebase 对其进行检查,然后返回该用户的数据。
我很想举一个例子,说明我应该如何以类似的方式验证我的行为。
解决方案
认证路由可以使用动作组合来实现。这是从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
}
推荐阅读
- maven-3 - mvn install - 执行
- ios - Obj-C - 使用 AFNetworking 块之外的数据
- c# - 一段时间的统一行动
- ruby-on-rails - 如何修复共享相同 ID 的 Rails Active Storage blob
- python-3.x - 在创建具有已知不良数据的数据帧时强制执行数据类型
- python - 我不明白为什么范围函数增量参数适用于切片运算符
- .net - 我的 .Net 代码在命名管道中出现 40 错误,但 Excel 连接正常
- java - 继承中的方法调用有问题
- php - WooCommerce 在快速编辑时保存自定义产品字段
- bash - 计算机启动后 Anacrontab 未运行计划的 bash 脚本