6

Hier ist ein authorisation example from Play Documentation (Version 2.0.4, habe ich versucht, eine neuere Version dieses Dokuments zu finden, konnte aber nicht):In Play 2.4 mit DI, wie wird eine Serviceklasse im Merkmal "Gesichert" verwendet?

trait Secured { 

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

    def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Auth.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)) 
    } 
} 

Insgesamt ist dieses ziemlich einfach ist, und ich würde mit etwas gehen mag wie Dies.

nun im Play 2.4 die empfohlene Methode ist nicht Singletons mehr zu verwenden (wie UserDAO oben), aber Klassen und Laufzeit DI statt (siehe migration guide oder DI docs).

Zum Beispiel sind meine Dienste und Repository-Klassen wie folgt definiert:

class AuthService @Inject()(accountRepo: AccountRepository) { } 

class AccountRepository { } 

mit Spiel-2.4 und DI in Gebrauch ist, was ist die empfohlene/„richtig“/einfachste Art und Weise halten, einen Service zu erhalten oder DAO (wie AuthService in meinem Fall, oder UserDAO im Dok-Beispiel) in einem Merkmal wie Secured?

Oder sollen Sie heutzutage die Autorisierung für Controller auf eine ganz andere Weise implementieren als die Verwendung eines solchen Merkmals?


Ich kann es in dieser Richtung funktioniert:

trait Secured { 
    val authService = GuiceUtils.inject[AuthService]  
    // ... 
} 

einen Helfer wie folgt aus:

object GuiceUtils { 
    lazy val injector = new GuiceApplicationBuilder().injector()  
    def inject[T: ClassTag]: T = injector.instanceOf[T] 
} 

Aber nach einer Antwort in einem related question:

In Play können Sie den Injektor direkt verwenden solange die Anwendung Merkmal in Geltungsbereich ist. Dies wird jedoch in Produktionscode nicht als gute Praxis angesehen.

Wenn das wahr ist, was gute Praxis in diesem Anwendungsfall betrachtet wird?

Antwort

16

Ich denke, der einfachste Ansatz wäre, den authService in Ihrem Merkmal zu erklären, aber halten Sie es abstrakt, dann haben Sie den Controller, der es erweitert die Injektion handhaben (ich glaube, so funktioniert MessagesApi/I18nSupport Injektion). So könnten Sie tun:

trait Secured { 
    val authService: AuthService 
    ... 
} 

controller Application @Inject()(override val authService: AuthService) extends Controller with Secured { 
    ... 
} 
+1

Danke, ziemlich einfach in der Tat! (Musste 'override val 'hinzufügen, um es kompilieren zu lassen.) – Jonik

+0

, aber dieser Weg Controller hat Wissen über zugrunde liegende Implementierung - authService - die nur in' Secured 'Eigenschaft verwendet werden kann. Gibt es eine Möglichkeit, es nur zum Merkmal zu injizieren? Wie im Kuchenmuster? – freakman

Verwandte Themen