Ecco un authorisation example from Play Documentation (versione 2.0.4, ho cercato di trovare una nuova versione di questo documento, ma non poteva):In Play 2.4 con DI, come utilizzare una classe di servizio nel tratto "Protetto"?
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))
}
}
Nel complesso questo è piuttosto semplice, e mi piacerebbe andare con qualcosa di simile Questo.
Ora, in Play 2.4 il metodo raccomandato è non usare single più (come UserDAO sopra), ma le classi e DI runtime (si veda migration guide o DI docs).
Per esempio, il mio servizio e le classi di repository sono definiti in questo modo:
class AuthService @Inject()(accountRepo: AccountRepository) { }
class AccountRepository { }
del gioco con il 2.4 e DI in uso, qual è il/"corretta"/modo più semplice consigliato di entrare in possesso di un servizio o DAO (come AuthService
nel mio caso o UserDAO
nell'esempio di documento) in un tratto come Secured
?
O si suppone oggi che si debba implementare l'autorizzazione per i controller in un modo completamente diverso dall'utilizzo di tale tratto?
posso farlo funzionare in questo senso:
trait Secured {
val authService = GuiceUtils.inject[AuthService]
// ...
}
Utilizzando un aiuto come questo:
object GuiceUtils {
lazy val injector = new GuiceApplicationBuilder().injector()
def inject[T: ClassTag]: T = injector.instanceOf[T]
}
Ma secondo una risposta in un related question:
In Play è possibile utilizzare direttamente l'iniettore purché il tratto dell'applicazione sia compreso. Ma questo non è considerato una buona pratica nel codice di produzione .
Se questo è vero, ciò che è considerati buone pratiche in questo caso d'uso?
Grazie, davvero semplice! (Doveva aggiungere 'override val' per renderlo compilato.) – Jonik
ma in questo modo il controller ha una conoscenza dell'implementazione sottostante - authService - che può essere utilizzata solo nel tratto 'Secured'. C'è un modo per iniettarlo solo per tratto? Come nel modello di torta? – freakman