2013-11-08 3 views
7

Это простой пример контроллера в Play Framework, где каждое действие проверяет сеанс - если пользователь вошел в системупроверка авторизации в контроллере - Scala/Play

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, 2.10.3 Scala, Java 1.8.0-еа 64-битную

UPDATE - решаемые Спасибо за все ваши идеи, решение теперь найдено, см мой ответ.

ответ

4

Решение состоит в том, чтобы использовать Action Composition и создать собственное действие.

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

} 
+0

Но ActionBuilder не является общим. –

1

Вы можете использовать Filter, который применяется к каждому запросу приложения. Однако тогда вам нужно будет иметь код Filter, чтобы разрешить доступ к определенным URL-адресам без действительного сеанса, иначе пользователь не сможет войти в систему в первую очередь.

+0

Спасибо за ваше предложение - это имеет смысл, хотя у меня возникают проблемы с поиском хороший пример того, как использовать фильтр в частности, воспроизводить объект контроллера. – Caballero

9

Для достижения этой цели вы можете воспользоваться 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 scala добавьте

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

Дополнительную информацию о фильтрах см. На официальном сайте docs

+0

Спасибо, я уже смотрел в Action Composition в течение нескольких часов и просто наткнулся на довольно простое решение. – Caballero

Смежные вопросы