【发布时间】:2013-12-19 01:50:11
【问题描述】:
我正在尝试在我的 Play 2.2.1 应用中实现身份验证,但我不知道如何使用返回 Future[Result] 的操作使其工作。
这篇文章描述的非常接近我正在尝试做的事情,除了没有返回 Future[Result]:
Play 2.0 Framework, using a BodyParser with an authenticated request
如何让它与 Futures 一起使用? IE。我将如何实现这个功能:
def IsAuthenticated(f: => String => Request[Any] => Future[Result])
或者,更好的是,这个函数:
def IsAuthenticated[A}(b:BodyParser[A])(f: => String => Request[Any] => Future[Result])
将输入此函数:
def AuthenticatedUser(g: Account => Request[AnyContent] => SimpleResult) = IsAuthenticated {...}
在我的控制器中包装异步操作?
这部分我可以做:
def IsAuthenticated(f: => String => Request[AnyContent] => Future[SimpleResult]) = {
Security.Authenticated(email, onUnauthorized) {
user => Action.async(request => f(user)(request))
}
}
但如果我尝试在包装函数中使用 IsAuthenticated:
def AuthenticatedUser(g: Account => Request[AnyContent] => Future[SimpleResult]) = IsAuthenticated {
email => implicit request => Account.find(email).map {
opt => opt match {
case Some(account) => g(account)(request)
case None => Future(onUnauthorized(request))
}
}
}
(Account.find 返回一个 Future[Option[Account]] '因为它是一个可能需要一些时间的 mongodb 调用。做正确的未来事情的愿望是让我现在如此悲伤的原因)
我无法让 AuthenticatedUser 满足编译器的要求。它说它得到的是 Future[Future[SimpleResult]] 而不是 Future[SimpleResult]。
那么,如何最好地构建整个东西?我需要能够制作依赖于异步数据库调用的身份验证包装器。
我确定我只是很密集并且缺少一些明显的东西......
编辑:这就是我最终的结果。感谢 Jean 为我指明了正确的方向。
我在寻找 AuthenticatedController 时发现了它,它与我正在寻找的非常接近。我想要两种类型的身份验证:用户(经过身份验证的用户)和管理员(为管理任务包装代码)。
package controllers
import models.Account
import play.api.mvc._
import scala.concurrent.Future
trait Secured {
class AuthenticatedRequest[A](val account: Account, request: Request[A]) extends WrappedRequest[A](request)
object User extends ActionBuilder[AuthenticatedRequest] {
def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[SimpleResult]) = {
request.session.get("email") match {
case Some(email) => {
Account.find(email).flatMap {
case Some(account) => {
block(new AuthenticatedRequest(account, request))
}
case _ => Future(Results.Redirect(routes.Index.index()))
}
}
case _ => Future(Results.Redirect(routes.Index.index()))
}
}
}
object Administrator extends ActionBuilder[AuthenticatedRequest] {
def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[SimpleResult]) = {
request.session.get("email") match {
case Some(email) => {
Account.find(email).flatMap {
case Some(account) => if (account.admin) {
block(new AuthenticatedRequest(account, request))
} else {
Future(Results.Redirect(routes.Index.index()))
}
case _ => Future(Results.Redirect(routes.Index.index()))
}
}
case _ => Future(Results.Redirect(routes.Index.index()))
}
}
}
}
【问题讨论】:
-
如果您尝试
case None => Future.successful(onUnauthorized(request))会怎样?虽然,@Jean 的方法似乎更好。
标签: scala authentication playframework-2.2