当前位置:  开发笔记 > 编程语言 > 正文

在带有DI的Play 2.4中,如何在"安全"特性中使用服务类?

如何解决《在带有DI的Play2.4中,如何在"安全"特性中使用服务类?》经验,为你挑选了1个好方法。

这是Play文档的一个授权示例(版本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(参见迁移指南或DI文档).

例如,我的服务和存储库类定义如下:

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

class AccountRepository { }

使用Play 2.4和DI时,建议/"正确"/最简单的方法是获取服务或DAO(如AuthService我的情况,或者UserDAO在doc示例中)这样的特性是Secured什么?

或者您现在是否应该以不同于使用此类特征的方式实施控制器授权?


我可以按照以下方式开展工作:

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

使用这样的帮助:

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

但根据相关问题的答案:

在Play中,只要Application trait在范围内,您就可以直接使用注入器.但这不是生产代码中的好习惯.

如果这是真的,那么在这个用例中认为是好的做法?



1> 小智..:

我认为最简单的方法是在你的trait中声明authService但保持抽象,然后让扩展它的控制器处理注入(我相信这就是MessagesApi/I18nSupport注入的工作原理).所以你可以这样做:

trait Secured {
  val authService: AuthService
  ...
}

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

推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有