【问题标题】:Extend SecureActionBuilder to Validate Request Before Parsing the Body扩展 SecureActionBuilder 以在解析正文之前验证请求
【发布时间】:2014-09-28 14:42:56
【问题描述】:

我正在编写一个将多部分文件作为输入并将它们上传到 S3 实例的 Web 应用程序。由于某些文件可能非常大,因此我使用自定义的 Body Parser 在块进入时将它们发送到 S3。

我想在上传文件之前对请求进行验证(检查用户是否有权限/足够的空间等)。通过阅读 Play 文档,扩展 ActionBuilder 似乎是正确的方法。我在 SecureSocial 中注意到,有一个 SecureActionBuilder,我相信我应该扩展它以构建一个安全的操作(这就是我想要的)。

我尝试了这个简单的测试,看看我是否可以打印出 userId,从而能够根据用户执行操作。

object FileValidationAction extends SecuredActionBuilder {
  def invokeBlock[A](request: SecuredRequest[A], block: SecuredRequest[A] => Future[SimpleResult]) = {
    Logger.info("User id is " + request.user.userProfile.userId)
    block(request)
  }
}

但是,该方法从未被调用。

接下来,我尝试覆盖 SecuredActionBuilder 对象中的方法:

object FileValidationAction extends SecuredActionBuilder {
  override def invokeBlock[A](request: Request[A], block: SecuredRequest[A] => Future[SimpleResult]) = {
    val securedResult: Option[SecuredRequest[A]] = request match {
      case r: SecuredRequest[A] => Option(r)
      case _ => None
    }
    Logger.info("Calling action ------- WOO!")
    securedResult match {
      case Some(r) =>
        block(r)
      case _ =>
        Future.successful(Forbidden)
    }
  }
}

该方法被调用,但传入的请求不是我希望的 SecuredRequest。

如何使用自定义正文解析器构建 SecuredAction,我可以在它完成(甚至开始)上传之前对其进行验证?

编辑:

为了澄清,我将使用以下方法签名调用 Action:

def upload = FileValidationAction(streamingBodyParser(streamConstructor)) { request =>

【问题讨论】:

    标签: scala playframework securesocial


    【解决方案1】:

    问题是您没有调用 SecuredActionBuilder 中的原始代码,该代码实际检查用户是否存在并构造 SecuredRequest 实例。

    这样的事情应该可以工作:

    // A sample usage of the action
    def checkFile = FileValidationAction { request =>
        Ok("")
      }
    
    // The builder implementation
      object FileValidationAction extends FileValidationActionBuilder {
        def apply[A]() = new FileValidationActionBuilder()
      }
    
      class FileValidationActionBuilder(authorize: Option[Authorization[DemoUser]] = None) extends SecuredActionBuilder(authorize) {
        def validateFile[A](block: SecuredRequest[A] => Future[SimpleResult]): SecuredRequest[A] => Future[SimpleResult] = { securedRequest =>
          Logger.info(s"User id is ${securedRequest.user.main.userId}")
          block(securedRequest)
        }
    
        override def invokeBlock[A](request: Request[A], block: (SecuredRequest[A]) => Future[SimpleResult]): Future[SimpleResult] = {
          invokeSecuredBlock(authorize, request, validateFile(block))
        }
      }
    

    您需要将其添加到您计划使用此操作的控制器中。如果您需要在多个控制器中使用它,请创建一个您可以使用它扩展的特征。

    还请注意,在此示例代码中,我使用了示例中的DemoUser 类型。您需要将其更改为您在应用中使用的类型来代表用户。

    【讨论】:

    • 恐怕还是有错误。 BodyParser 在文件验证发生之前执行。在上传之前,我需要对文件进行一些检查。有没有办法做到这一点?
    • 我在编辑中添加了显示我将如何使用自定义操作。事实上,仅使用安全操作也是如此。在进行正文解析之前有什么方法可以验证用户吗?
    • Actions 使用 BodyParser 解析请求,以便实现您需要的 EssentialAction。 EssentialActions 使您无需解析内容即可访问请求标头。我现在模块中没有类似的东西。我会尝试看看如何添加对此的支持。
    • 好的,我会在这里接受答案,并在 github repo 上发布问题。再次感谢。
    • 这是什么库?我的意思是你使用 SecuredActionBuilder ?
    猜你喜欢
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    相关资源
    最近更新 更多