0

我正在使用 Scala & Play 2.0

我有一个这样的网址:

/v1/people/search/MTIyOjg3YjYzNmU1YTk5MDdkYjY2MzAyODZiM2RkNTMzYzYw

在我的路线文件中:

POST /v1/people/search/:authToken controllers.v1.Application.searchPeople(authToken: String)

我要做的是创建一个安全特征并获取 :aythToken 并通过自定义操作进行验证,该操作在我的函数/方法调用中替换它:

使操作成为 CustomAuthAction

def searchPeople(authToken: String) = Action { 隐式请求 => }

这样我就可以拒绝基于已解析的请求:authToken 而无需将此值设置为 cookie,我已经知道如何做到这一点。

那么我怎样才能把已经通过的 play :authToken 传递给自定义操作呢?

谢谢


这是我的解决方案:

case class CheckSessionRequest(val user: User, request: Request[AnyContent]) extends   WrappedRequest(request)

def RequireAuthToken(f: CheckSessionRequest => Result): Action[AnyContent] = {
Action { request =>
UserValidation.findUserByAuthToken(StringUtil.getAuthTokenFromURL(request.toString)).map     { user =>
f(CheckSessionRequest(user, request))
}.getOrElse( // STRANGE ERROR
Ok(Json.generate(StatusHandler("failed","Unknown Login Error","{}"))).withHeaders(
CONTENT_TYPE -> "application/json"
) 
)
}
}
4

2 回答 2

2

让我引用 Play 文档:

Play 应用程序收到的大多数请求都由 Action 处理。

play.api.mvc.Action 基本上是一个 (play.api.mvc.Request => play.api.mvc.Result) 函数,它处理请求并生成要发送给客户端的结果。

如果您查看动作组合,它会清楚地解释您如何基本上创建自定义动作:

def LoggingAction(f: Request[AnyContent] => Result): Action[AnyContent] = {
  Action { request =>
    Logger.info("Calling action")
    f(request)
  }
}

我做过类似的工作,看起来就是这样,有点复杂但很有趣

trait SecuredController[UserModel<:ValidableEmail] {

  type LoggedRequestHandler  =  UserModel =>Request[AnyContent] => Result

  def loggedUser(implicit request:Request[_]):Option[UserModel]

  def WithAuthenticatedUser( onUserAuthenticated: => LoggedRequestHandler,
                             onUserAuthenticatedButEmailNotValidated: LoggedRequestHandler,
                             onUnauthenticated: Request[AnyContent]=>Result) = {
    Action{
     implicit request =>
        loggedUser match{
          case Some(user) if (user.emailValidated) => onUserAuthenticated(user)(request)
          case Some(user) if(!user.emailValidated) => onUserAuthenticatedButEmailNotValidated(user)(request)
          case None => onUserNotLogged(request)
        }
    }
  }

这个 trait 基本上定义了两种方法:

  • 一种能够确定请求中是否存在当前登录用户(通常使用会话)
  • 一个基本上创建一个具有三种可能结果的动作:
    • onUserAuthenticated 以防有已登录用户的电子邮件已验证
    • onUserAuthenticatedButEmailNotValidated 如果有记录但未验证电子邮件
    • onUserNotLoggedif 有记录但未验证电子邮件

LoggedRequestHandler 只是一个函数的类型别名,它采用我的用户 UserModel 并创建一个函数 Request => Result

一旦你有了这个,你基本上可以写如下

object EmployeeController extends SecuredController[Employee]{

    def loggedUser(implicit request:Request[_]):Option[Employee]

    def ViewPay = WithAuthenticatedUser{
       ShowPay, 
       ShowEmailNotValidated,
       ShowUserNotLogged        
    }

    def ShowPay(employee:Employee): Request[AnyContent] => Result = {

    }
    def ShowEmailNotValidated(employee:Employee): Request[AnyContent] => Result = {

    }

    def ShowUserNotLogged: Request[AnyContent] => Result = {

    }



}
于 2012-12-13T09:31:41.083 回答
1

这是我想出的解决方案,效果很好。

case class CheckSessionRequest(val user: User, request: Request[AnyContent]) extends   WrappedRequest(request)

def RequireAuthToken(f: CheckSessionRequest => Result): Action[AnyContent] = {
    Action { request =>
     UserValidation.findUserByAuthToken(StringUtil.getAuthTokenFromURL(request.toString)).map     { user =>
      f(CheckSessionRequest(user, request))
     }.getOrElse( // STRANGE ERROR
      Ok(Json.generate(StatusHandler("failed","Unknown Login Error","{}"))).withHeaders(
       CONTENT_TYPE -> "application/json"
      ) 
    )
  }
}

然后用 RequireAuthToken 替换你的“Action”调用

于 2012-12-14T23:20:00.880 回答