如何扩展Play2 scala zentasks身份验证以自动获取用户

时间:2012-04-13 16:07:22

标签: scala playframework playframework-2.0

在Play2的zentasks示例中,我们有方法

def isAuthenticated(f: => String => Request[AnyContent] => Result) = {
  Security.Authenticated(username, onUnauthorized) { user =>
    Action(request => f(user)(request))
  }
}

我想要做的是添加另一种方法,如果我想直接从数据库中获取用户,我可以使用它。

在所有方法中添加包装器会有点无聊

def method() = isAuthenticated { username => implicit request =>
  UserDAO.findOneByEmail(username).map { user =>
    Ok(html.user.view(user))
  }.getOrElse(Forbidden)
}

我是函数式编程的新手,所有这些=>让我头晕目眩:)

有什么建议吗?

3 个答案:

答案 0 :(得分:5)

您可以定义另一种方法,例如IsAuthenticatedUser,它将采用User => Request[AnyContent] => Result类型的参数:

def IsAuthenticatedUser(f: User => Request[AnyContent] => Result) = IsAuthenticated { email => request =>
  UserDAO.findOneByEmail(email).map { user =>
    f(user)(request)
  }.getOrElse(Forbidden)
}

然后您可以按如下方式使用它:

def method = IsAuthenticatedUser { user => request =>
  Ok(html.user.view(user))
}

答案 1 :(得分:4)

这是最终的解决方案

trait Secured {

  def username(request: RequestHeader) = request.session.get(Security.username)

  def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Application.login)

  def withAuth(f: => String => Request[AnyContent] => Result) = {
    Security.Authenticated(username, onUnauthorized) { user =>
      Action(request => f(user)(request))
    }
  }

  def withUser(f: User => Request[AnyContent] => Result) = withAuth { username => implicit request =>
    UserDAO.findOneByUsername(username).map { user =>
      f(user)(request)
    }.getOrElse(onUnauthorized(request))
  }

}

用法:

object Application extends Controller with Secured {

  def index = withAuth { username => implicit request =>
    Ok(html.index(username))
  }

  def user() = withUser { user => implicit request =>
    val username = user.username
    Ok(html.user(user))
  }
}

如您所见,如果会话不存在,用户将被重定向到特征中指定的登录页面。

如果在DAO中找不到用户名,也是如此。

答案 2 :(得分:1)

半解决方案是将获取用户数据步骤封装到某个函数中并从模板级别(而不是每个操作)调用它,因为每个模板只是一个scala函数。

感谢这种方法,如果您使用相同的视图(甚至布局)有多个操作,则不必每次都获取已记录的用户,即:

user view中的

@defining(Application.getLoggedUser){ user =>
    @yourlayout("Welcome") {
        <h2>Hello @user.name</h2>
        ...
    } 
}