【问题标题】:Authorisation check in controller - Scala/Play控制器中的授权检查 - Scala/Play
【发布时间】:2013-11-08 20:41:52
【问题描述】:

这是 Play Framework 中控制器的一个简单示例,其中每个操作都会检查会话 - 如果用户已登录。

object Application extends Controller {

    def index = Action { implicit request =>
        if (request.session.isEmpty) {
            Redirect("/login")
        } else {
            Ok(views.html.index("index"))
        }
    }

    def about = Action { implicit request =>
        if (request.session.isEmpty) {
            Redirect("/login")
        } else {
            Ok(views.html.index("about"))
        }
    }

}

我想处理构造函数中的会话检查,而不是每个操作方法,但我不知道怎么做?它应该看起来像这样:

object Application extends Controller {

    //This is where the constructor would check if session exists
    //and if not - redirect to login screen

    def index = Action {
        Ok(views.html.index("index"))
    }

    def about = Action {
        Ok(views.html.index("about"))
    }

}

这可能吗?如果可以,怎么办?

我的堆栈是 Play Framework 2.2.1、Scala 2.10.3、Java 1.8.0-ea 64bit

更新 - 已解决感谢您的所有想法,现已找到解决方案,请参阅我的回答。

【问题讨论】:

    标签: scala playframework playframework-2.0


    【解决方案1】:

    您可以利用Action Composition 来实现此目的。来自文档:

    import play.api.mvc._
    
    class AuthenticatedRequest[A](val username: String, request: Request[A]) extend WrappedRequest[A](request)
    
    object Authenticated extends ActionBuilder[AuthenticatedRequest] {
      def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) =>Future[SimpleResult]) = {
        request.session.get("username").map { username =>
          block(new AuthenticatedRequest(username, request))
        } getOrElse {
          Future.successful(Forbidden)
        }
      }
    }
    

    然后你可以简单地做:

    def index = Authenticated {
        Ok(views.html.index("index"))
    }
    

    或者,您可以设置一个过滤器(如@Robin Green 建议的那样),如下所示:

    object AuthFilter extends Filter {
    
      override def apply(next: RequestHeader => Result)(rh: RequestHeader): Result = {
        rh.session.get("username").map { user =>
          next(rh)
      }.getOrElse {
        Redirect("/login")
      }
    }
    

    在 Global.scala 中添加

    override def doFilter(action: EssentialAction) = AuthFilter(action)
    

    更多关于Filters,请看官方docs

    【讨论】:

    • 谢谢,我已经研究动作组合几个小时了,只是偶然发现了一个相当简单的解决方案。
    【解决方案2】:

    解决方案是使用动作组合并创建自定义动作。

    Auth.scala:

    package core
    
    import play.api.mvc._
    import scala.concurrent._
    import play.api.mvc.Results._
    
    object AuthAction extends ActionBuilder[Request] {
    
        def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[SimpleResult]) = {
            if (request.session.isEmpty) {
                //authentication condition not met - redirect to login page
                Future.successful(Redirect("/login"))
            } else {
                //proceed with action as normal
                block(request)
            }
        }
    
    }
    

    Application.scala:

    package controllers
    
    import play.api._
    import play.api.mvc._
    import core._
    
    object Application extends Controller {
    
        def index = AuthAction {
            Ok(views.html.index("You are logged in."))
        }
    
    }
    

    【讨论】:

    • 但是 ActionBuilder 不是泛型的。
    【解决方案3】:

    看看 Deadbolt:https://github.com/schaloner/deadbolt-2。有详尽的示例和指南。

    在我的 Play 2 项目中完美运行。

    【讨论】:

      【解决方案4】:

      您可以使用Filter,它适用于应用程序中的每个请求。但是,您需要在 Filter 中添加一些代码,以允许在没有有效会话的情况下访问某些 URL,否则用户将无法首先登录。

      【讨论】:

      • 感谢您的建议 - 这是有道理的,尽管我很难找到一个很好的例子来说明如何在专门的播放控制器对象上使用过滤器。
      猜你喜欢
      • 1970-01-01
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      • 2015-06-22
      • 1970-01-01
      相关资源
      最近更新 更多