- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
简单地说:我的应用程序使用 Play web framework版本 2.5.1。我想使用the Deadbolt authorization system ,和Slick访问我的数据库中的用户授权信息。我怎样才能做到这一点? Deadbolt 专为 Play 打造,Play 配有开箱即用的集成 Slick,因此即使不是很容易,也应该是可能的。
基于"Integrating Deadbolt"从 Deadbolt 文档中,我扩展了 DeadboltHandler
特征。其摘要getSubject()
方法似乎是进行数据库查询的地方(如the documentation所示,但没有任何示例)。该方法接收 AuthenticatedRequest
作为参数并返回Subject
,基本上是经过身份验证的用户 ID,以及角色和权限(授权)。
我被困住了,因为 Play 带有 Slick integration ,该文档仅描述如何在 Play Controller 中使用它。 (注意,我想使用依赖注入(inject)来执行此操作,因为使用全局查找已被弃用并且容易出错)
我在 Controller 中成功使用Deadbolt来限制对某些资源的访问,但 Controller 似乎不适合Deadbolt进行数据库查询以获取授权详细信息(如果是的话,那么 DeadboltHandler
将毫无意义)。 Controller 构造函数签名定义类似于(注意 Controller 访问存储 Web 内容的默认数据库而不是授权数据库):
class Application @Inject()(
dbConfigProvider: DatabaseConfigProvider,
playConfig: play.api.Configuration,
deadbolt: DeadboltActions
) extends Controller {
这有效。然而,类似地注释 DeadboltHandler
扩展名 @Inject
无法提供对数据库的流畅访问:
class AuthHandler @Inject()(@play.db.NamedDatabase("auth") dbConfigProvider: DatabaseConfigProvider)
extends DeadboltHandler {
结果是
not enough arguments for constructor AuthHandler: (dbConfigProvider: play.api.db.slick.DatabaseConfigProvider)services.AuthHandler.
Unspecified value parameter dbConfigProvider.
显然,Play 为 Controller 做了一些特殊的事情,因此 @Inject
注释有效,但我对此缺乏理解。我认为这是使用注入(inject)器而不是 new
构建 Controller 的本质。关键字,但我通过 Play 源代码的搜索未能告诉我到底发生了什么。如果我能找到这一点,也许我可以模仿该技术来构建 DeadboltHandler
.
我发现游戏附带了类似 GuiceInjector 的类和 GuiceInjectorBuilder ,这听起来好像它们可能是解决方案的一部分,但我的实验尚未向我展示如何使用它们,以及是否有任何文档说明如何在 DeadboldHandler
的特定上下文中使用它们。扩展名,我错过了。
我发现了上一个问题:Scala (Play 2.4.x) How to call a class with @inject() annotation ,这似乎非常切题。不幸的是,尽管原发帖者提出了六条后续评论,但尚未得到答复。我觉得如果我知道了这个问题的答案,我就会知道这个问题的答案,尽管我的问题非常具体:如何使用Play和Deadbolt和彼此顺利(在Scala中)。
最让我困惑的是,这似乎应该是很常见的事情,要么在文档中提到,要么已经在 SO 上被询问过。我未能找到任何此类引用资料通常意味着我正在做一些非常错误的事情,以至于没有其他人有机会谈论它。当然,它似乎应该足够简单,以至于我乐观地希望我错过了一些非常基本的东西,并且我期待着某个好心人告诉我这些知识。
最佳答案
正如您在问题中所指出的,检索用户的位置位于 DeadboltHandler.getSubject
中。实际上,您可以将特定于数据库的代码移至其自己的类中,因此在本例中我就是这么做的。
这是DeadboltHandler
的通用实现;您应该能够将其放入代码中并几乎按原样使用它,因为持久性细节将在稍后处理。
import javax.inject.{Inject, Singleton}
import be.objectify.deadbolt.scala.models.Subject
import be.objectify.deadbolt.scala.{AuthenticatedRequest, DeadboltHandler, DynamicResourceHandler}
import models.{LogInForm, User}
import play.api.mvc.{Request, Result, Results}
import play.twirl.api.HtmlFormat
import views.html.security.denied
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
@Singleton
class MyDeadboltHandler @Inject() (authSupport: AuthSupport) extends DeadboltHandler {
override def beforeAuthCheck[A](request: Request[A]): Future[Option[Result]] = Future {None}
override def getDynamicResourceHandler[A](request: Request[A]): Future[Option[DynamicResourceHandler]] = Future {None}
/**
* Get the current user.
*
* @param request the HTTP request
* @return a future for an option maybe containing the subject
*/
override def getSubject[A](request: AuthenticatedRequest[A]): Future[Option[Subject]] =
Future {
request.subject.orElse {
// replace request.session.get("userId") with how you identify the user
request.session.get("userId") match {
case Some(userId) => authSupport.getUser(userId)
case _ => None
}
}}
/**
* Handle instances of authorization failure.
*
* @param request the HTTP request
* @return either a 401 or 403 response, depending on the situation
*/
override def onAuthFailure[A](request: AuthenticatedRequest[A]): Future[Result] = {
def toContent(maybeSubject: Option[Subject]): (Boolean, HtmlFormat.Appendable) =
maybeSubject.map(subject => subject.asInstanceOf[User])
.map(user => (true, denied(Some(user))))
.getOrElse {(false, views.html.security.logIn(LogInForm.logInForm))}
getSubject(request).map(maybeSubject => toContent(maybeSubject))
.map(subjectPresentAndContent =>
if (subjectPresentAndContent._1) Results.Forbidden(subjectPresentAndContent._2)
else Results.Unauthorized(subjectPresentAndContent._2))
}
}
现在,在主题尚未放入请求中的情况下,访问数据库的需要已减少。请注意有关将 request.session.get("userId")
替换为您标识用户的注释。
然后,AuthSupport
类提供对主题持久性的访问。这将 DB 访问与 DeadboltHandler 隔离开来。这非常简单,主要是因为您将使用 Slick 查询填写此内容。
@Singleton
class AuthSupport @Inject()(dbConfigProvider: DatabaseConfigProvider) {
// set up your usual Slick support
// use Slick to get the subject from the database
def getUser(userId: String): Option[User] = ???
}
要公开这一点,您需要创建一个模块并将其注册到 application.conf
中。
import be.objectify.deadbolt.scala.DeadboltHandler
import be.objectify.deadbolt.scala.cache.HandlerCache
import security.{AuthSupport, MyDeadboltHandler, MyHandlerCache}
import play.api.inject.{Binding, Module}
import play.api.{Configuration, Environment}
class CustomBindings extends Module {
override def bindings(environment: Environment,
configuration: Configuration): Seq[Binding[_]] =
Seq(
bind[DeadboltHandler].to[MyDeadboltHandler],
bind[AuthSupport].toSelf,
// other bindings, such as HandlerCache
)
}
在 application.conf
中声明它是使用 play.modules.enabled
的常见问题:
play {
modules {
enabled += be.objectify.deadbolt.scala.DeadboltModule
enabled += modules.CustomBindings
}
}
关于scala - 如何集成Play(Web框架)、Deadbolt(授权)和Slick(数据库访问),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36409098/
所以我的应用程序的评论显示在我的游戏控制台中,但是由于某种原因,当我在 google Play 商店上访问我的应用程序链接并以普通用户的身份查看它时,我没有收到新评论的通知,我的显示了 13 条评论,
一旦我在 2.3 play 项目上运行 'sbt compile',我就不能再使用 'sbt compile' 来编译任何 Play 2.2.x 项目。这是我运行 sbt 命令时的错误。 [info]
我有点困惑,想得到一个解释。 我正在使用 Java Play 2 和 Akka Actor 。我使用 play run 启动系统。 不过,我刚刚看到一个视频,使用了命令: play akka star
当我玩游戏时,我遇到两个选择play.api.mvc和 play.mvc包裹 有什么不同? 最佳答案 从戏! 2 文档: The API available in the play.api packa
从 2.3 迁移到 2.4 后,我收到此错误。我应该使用的正确导入语句是什么? error: value routesImport is not a member of object play.Pla
所以我在 google play 上有一个应用程序已经将近 6 个月了,最近两个月我更新了我的应用程序屏幕截图,从那时起,每次我更新我的应用程序时,我都开始收到应用程序拒绝。 上次我提出上诉并被接受,
我有以下代码: Snapshots.OpenSnapshotResult result; result = Games.Snapshots.open(googleApiClient, "save",
在过去 72 小时内,我为 Google Play 开发者计划支付的 Google 电子钱包付款显示为“您的购买正在处理中”。我知道这可能需要长达 48 小时,但这是他们处理时间最坏情况之后的一整天。
我在 Play 商店发布了应用程序,我不知道为什么应用程序显示预注册,我想为我的用户提供直接下载选项。伸出援手将不胜感激。 最佳答案 instructions for pre-registration
我有一个 PHP 后端,它与 Google Play 服务集成以验证从 APP 进行的购买。购买信息返回收据和签名,我需要验证购买是否正确。 我收到: { ...rest of the data
我在 Google Play Developer Console 上创建了我的 Android 应用程序的草稿。我已经填写了所有需要的信息。必需的步骤之一是“内容评级”。我已填写表格以自动分配 Goo
我已经设置好了 com.typesafe.play play_2.13 2.7.4 在项目 pom.xml 中。但是,当我尝试遵循this tutorial时,语句 pla
我在 Play 商店上发布了一个应用程序,并收到了一些评论。在Google Play开发者控制台中,我在一些评论中看不到应用程序的版本。这是我在“应用程序”标题下找到的内容。 版本代码 — 版本名称
假设 A 是所有者。我希望我们团队的 B、C 和 D 用户能够上传我们应用程序的新版本。这可能吗?来自 this我不太清楚用户有什么样的权限。如果有人对这部分有任何经验,欢迎。 最佳答案 您需要 go
我正在尝试将应用重新提交到 Google Play,但我似乎可以找到一种技术上的方法来实现此目的。 我对“您的应用主要针对 COPPA 定义的 13 岁以下 child 吗?”的回答是肯定的,然后在不
我想分享一下我在分析 Google Play 控制台的新功能时遇到的情况,并尝试找到解决方案。 正如你们许多人可能已经知道的那样,Google 已在 Google Play 控制台上发布了更新并引入了
我有两个用 playframework 编写的应用程序。我想加入另一个。我有一个数据库,我想在它们之间共享我的登录类。应用程序对类、方法、变量使用不同的名称。 我怎样才能实现它?我应该创建 jar 版
对于我的硕士论文,我需要自动将来自 Google Play 的不同 Android 应用程序的信息写入一个文本文件。所以我使用 perl 脚本语言来实现这种自动化。我的 perl 脚本可以在 Goog
我想测试子项目是如何工作的,尤其是 routes在主项目 ( this was not visible before ) 中考虑了子项目的数量。 我在这里阅读了文档: https://github.c
我正在使用 Play 框架 2.1.2,我有一个 handlere 方法返回一个 Promise,如 Play 的 2.1.2 documentation 中所述 但是 Play 抛出编译错误说: C
我是一名优秀的程序员,十分优秀!