这是一个authorisation example from Play Documentation(版本2.0.4;我试图找到此文档的更新版本但不能):
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))
}
}
总的来说,这非常简单,我想用这样的东西。
现在,在Play 2.4中,推荐的方法是不再使用单例(如上面的UserDAO),而是使用类和运行时DI(参见migration guide或DI docs )。
例如,我的服务和存储库类定义如下:
class AuthService @Inject()(accountRepo: AccountRepository) { }
class AccountRepository { }
使用Play 2.4和DI时,建议/“正确”/最简单的方法是获取服务或DAO(在我的情况下为AuthService
,或在文档中为UserDAO
例如)Secured
?
或者您现在是否应该以不同于使用此类特征的方式实施控制器授权?
我可以按照以下方式开展工作:
trait Secured {
val authService = GuiceUtils.inject[AuthService]
// ...
}
使用这样的助手:
object GuiceUtils {
lazy val injector = new GuiceApplicationBuilder().injector()
def inject[T: ClassTag]: T = injector.instanceOf[T]
}
但根据related question中的答案:
在Play中,只要应用程序可以直接使用注射器 特质在范围内。但这不是一个好的做法 生产代码。
如果这是真的, 在这个用例中被认为是好习惯吗?
答案 0 :(得分:16)
我认为最简单的方法是在你的trait中声明authService但保持抽象,然后让扩展它的控制器处理注入(我相信这就是MessagesApi/I18nSupport
注入工作的方式)。所以你可以这样做:
trait Secured {
val authService: AuthService
...
}
controller Application @Inject()(override val authService: AuthService) extends Controller with Secured {
...
}