scala - Play Framework : How to deal with api keys

标签 scala playframework api-key

我已经实现了一个 REST API,它使用 JWT(Json Web token )处理用户授权,并且工作正常。现在我想知道如何处理 API key 以防止未经授权的应用程序使用我的 API。

这个想法是在请求 header 中添加 API key 并为其实现自定义操作构建器。现在的问题是:由于我已经有一个处理授权 token 的自定义操作构建器,我该如何集成新的自定义操作构建器?

假设这是我的 JWT 自定义操作构建器...

class ApiRequest[A](
  val token: Token,
  request: Request[A]) extends WrappedRequest[A](request) {

  ...
}

class SecuredAction extends ActionBuilder[ApiRequest] {

  def invokeBlock[A](request: Request[A], block: (ApiRequest[A]) => Future[SimpleResult]) = {
  ...
  }
}

...这是我的 api_key 自定义操作构建器
class ApiKeyRequest[A](
  val apiKey: String,
  request: Request[A]) extends WrappedRequest[A](request) {

  ...
}

class ApiKeyAction extends ActionBuilder[ApiKeyRequest] {

  def invokeBlock[A](request: Request[A], block: (ApiKeyRequest[A]) => Future[SimpleResult]) = {
  ...
  }
}

...我如何在我的 Controller 中一起使用它们?
object MyController extends Controller {

  // here I need to compose SecuredAction with ApiKeyAction...
  def doSomething = SecuredAction.async { implicit request => 
    ...
  }
}

谢谢。

最佳答案

看看Action Composition ,它允许您检查和转换对操作的请求。如果您使用 Play 过滤器,那么它将在每次请求时运行。

例如,您可以创建一个 TokenAction 来检查请求,如果找到了 token ,则优化请求以包含基于 token 的信息,例如用户。如果没有找到 token ,则返回另一个结果,如未授权、重定向或禁止。

我创建了一个 SessionRequest ,它有一个带有可选登录用户的用户属性,它首先从数据库中查找一个现有的 session ,然后获取附加的用户并将其传递给请求

然后过滤器(WithUser)将拦截SessionRequest,如果没有用户可用,则将用户重定向到登录页面

// Request which optionally has a user
class SessionRequest[A](val user: Option[User], request: Request[A]) extends WrappedRequest[A](request)

object SessionAction extends ActionBuilder[SessionRequest] with ActionTransformer[Request, SessionRequest] {

  def transform[A](request: Request[A]): Future[SessionRequest[A]] = Future.successful {
    val optionalJsonRequest: Option[Request[AnyContent]] = request match {
      case r: Request[AnyContent] => Some(r)
      case _ => None
    }

    val result = {
      // Check if token is in JSON request
      for {
        jsonRequest <- optionalJsonRequest
        json <- jsonRequest.body.asJson
        sessionToken <- (json \ "auth" \ "session").asOpt[String]
        session <- SessionRepository.findByToken(sessionToken)
      } yield session
    } orElse {
      // Else check if the token is in a cookie
      for {
        cookie <- request.cookies.get("sessionid")
        sessionToken = cookie.value
        session <- SessionRepository.findByToken(sessionToken)
      } yield session
    } orElse {
      // Else check if its added in the header
      for {
        header <- request.headers.get("sessionid")
        session <- SessionRepository.findByToken(header)
      } yield session
    }

    result.map(x => new SessionRequest(x.user, request)).getOrElse(new SessionRequest(None, request))
  }
}

// Redirect the request if there is no user attached to the request
object WithUser extends ActionFilter[SessionRequest] {
  def filter[A](request: SessionRequest[A]): Future[Option[Result]] = Future.successful {
    request.user.map(x => None).getOrElse(Some(Redirect("http://website/loginpage")))
  }
}

然后你可以在一个 Action 上使用它
def index = (SessionAction andThen WithUser) { request =>
  val user = request.user
  Ok("Hello " + user.name)
}

我希望这会给你一个关于如何使用 Action 合成的想法

关于scala - Play Framework : How to deal with api keys,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23984334/

相关文章:

playframework - Play Framework 2

javascript - 使用 JavaScript 时如何保护 API Key?

vue.js - 如何使用 Nuxt 保护 API key 并进行验证

scala - Spark Scala 有条件地添加到 agg

scala - JDK升级NoClassDefFoundError后未加载gradle测试依赖项

java - Websocket 在 playframework 2 中向所有客户端发送数据

google-cloud-platform - 使用 Nodejs 在 google 云端点上工作时出现 "Unsupported auth type for "问题尝试此 API“- api_key :apiKey.”

scala - 使用隐式见证组合类型级函数

Scala 隐式类和函数

java - Play Framework JPA : how to implement one-to-many relationship?