7

这是 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

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

4

4 回答 4

9

您可以利用动作组合来实现这一点。从文档中:

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)

有关过滤器的更多信息,请参阅官方文档

于 2013-11-09T18:23:28.197 回答
5

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

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)
        }
    }

}

应用程序.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."))
    }

}
于 2013-11-09T20:10:58.937 回答
2

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

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

于 2013-11-08T20:52:07.923 回答
1

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

于 2013-11-08T20:46:37.940 回答