我正在编写一个Web应用程序,它将多部分文件作为输入并将它们上传到S3实例。由于某些文件可能非常大,我使用自定义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 =>
答案 0 :(得分:3)
问题在于您没有调用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
类型。您需要将其更改为您在应用中使用的类型以表示用户。