问题描述
这是来自Play文档的授权示例(2.0版. 4;我试图找到此文档的较新版本,但找不到):
Here's an authorisation example from Play Documentation (version 2.0.4; I tried to find a newer version of this document but couldn't):
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))
}
}
总的来说,这非常简单,我想使用类似的东西.
Overall this is pretty straightforward, and I'd like to go with something like this.
现在,在Play 2.4中,推荐的方法不再是 来使用单例(如上述UserDAO),而是改为使用类和运行时DI(请参见迁移指南,或 DI文档).
Now, in Play 2.4 the recommended way is not to use singletons anymore (like UserDAO above), but classes and runtime DI instead (see migration guide, or DI docs).
例如,我的服务和存储库类的定义如下:
For example, my service and repository classes are defined like this:
class AuthService @Inject()(accountRepo: AccountRepository) { }
class AccountRepository { }
使用Play 2.4和DI时,推荐的/正确的"/最简单的方式来获得服务或DAO(例如,在我的情况下为AuthService
,在doc示例中为UserDAO
)是什么?像Secured
这样的特质?
With Play 2.4 and DI in use, what is the recommended / "correct" / simplest way to get hold of a service or DAO (like AuthService
in my case, or UserDAO
in the doc example) in a trait like Secured
?
或者您今天是否应该以不同于使用这种特征的另一种方式来实现对控制器的授权?
Or are you nowadays supposed to implement authorisation for controllers in a whole another way than using such trait?
我可以按照以下方式进行工作:
I can make it work along these lines:
trait Secured {
val authService = GuiceUtils.inject[AuthService]
// ...
}
使用这样的助手:
object GuiceUtils {
lazy val injector = new GuiceApplicationBuilder().injector()
def inject[T: ClassTag]: T = injector.instanceOf[T]
}
但是根据相关问题中的答案:
如果是这样,在此用例中什么被认为是好的做法?
If that is true, what is considered good practice in this use case?
推荐答案
我认为最简单的方法是在trait中声明authService,但使其保持抽象,然后由对其进行扩展的控制器处理注入(我相信是MessagesApi/I18nSupport
注入的工作方式).因此,您可以这样做:
I think the simplest approach would be to declare the authService in your trait but keep it abstract, then have the controller which extends it handle the injection (I believe this is how MessagesApi/I18nSupport
injection works). So you could do:
trait Secured {
val authService: AuthService
...
}
controller Application @Inject()(override val authService: AuthService) extends Controller with Secured {
...
}
这篇关于在带有DI的播放2.4中,如何在“安全"中使用服务类.特征?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!