Check authorization in the controller - Scala / Play

This is a simple controller example in the Play Framework, where each action checks the session - if the user is logged in.

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

I would like to handle session validation in the constructor instead of each action method, but I just don't know how to do this? It should look something like this:

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

Is this possible, and if so, how?

My stack is Play Framework 2.2.1, Scala 2.10.3, Java 1.8.0-ea 64bit

UPDATE - SOLVED Thanks for all your ideas, a solution has now been found, see my answer.

+7
scala playframework
source share
4 answers

The solution is to use Action Composition and create your own action.

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.")) } } 
+4
source share

To achieve this, you can use Action Composition . From the documentation:

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

And then you can just do:

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

Alternatively, you can configure the filter instead (as suggested by @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") } } 

In Global.scala scala add

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

For more information about filters, see white papers .

+9
source share

Take a look at Deadbolt: https://github.com/schaloner/deadbolt-2 . Comprehensive examples and guidelines exist.

Works great on my Play 2 project.

+2
source share

You can use Filter , which applies to every application request. However, then you will need to have the code in Filter to allow access to specific URLs without a valid session, otherwise the user would not be able to log in first.

+1
source share

All Articles