首页 > 解决方案 > 相当于 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 对其进行检查,然后返回该用户的数据。

我很想举一个例子,说明我应该如何以类似的方式验证我的行为。

标签: scalaauthenticationplayframework

解决方案


认证路由可以使用动作组合来实现。这是从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
} 

推荐阅读