如何在Play应用程序中实现请求解密和响应加密?

时间:2015-05-25 14:25:56

标签: scala encryption playframework playframework-2.0 iterate

鉴于

trait CipherService {
  def decryptData(data: Array[Byte])(implicit ec: ExecutionContext): Future[DecryptionError \/ Array[Byte]
  def encryptEncrypt(data: Array[Byte)(implicit ec: ExecutionContext): Future[EncryptionError \/ Array[Byte]]
}

如何使用EssentialFilter实现请求解密和响应加密?感觉我被EnumerateeIteratee API困住了。

2 个答案:

答案 0 :(得分:0)

当你达到字节块的极限时,Iteratees和Enumeratees几乎就要走了。加密是一种非常低级别的操作,并且很难做到正确,因此这些工具同样是低级别,小型和精确的。

由于加密和解密数据很难做到,因此大多数Web框架都依赖于HTTPS而不是在应用程序层中实现它。

如果你正在使用HTTP,那么根据bettercrypto.org使用配置了OpenSSL的nginx:https://www.playframework.com/documentation/2.3.x/ConfiguringHttps

如果您在内部使用安全性并且想要通过网络加密数据,则应在传输模式下使用ipsec。

答案 1 :(得分:0)

trait CipherService {
  def decryptData(data: Array[Byte])(implicit ec: ExecutionContext): Future[DecryptionError \/ Array[Byte]]
  def encryptData(data: Array[Byte])(implicit ec: ExecutionContext): Future[EncryptionError \/ Array[Byte]]
}

trait BodyEncryptionFilter extends EssentialFilter with Results {

  import play.api.libs.concurrent.Execution.Implicits._

  val cipher: CipherService

  def apply(next: EssentialAction): EssentialAction = new EssentialAction {
    override def apply(requestHeader: RequestHeader): Iteratee[Array[Byte], Result] =
      Iteratee.consume[Array[Byte]]().mapM { encryptedBody => // Collect body bytes
        cipher.decryptData(encryptedBody) // Decrypt data
          .toEitherT   // Monad transformer
          .flatMapF { decryptedBody =>
            Enumerator(decryptedBody).run(next(requestHeader)) // Feed decrypted data to filter/action chain
              .flatMap { result => // Here is the action result
                result.body.run(Iteratee.consume[Array[Byte]]()) //Collect result body data
                  .flatMap { body =>
                    cipher.encryptData(body) // Ecnrypt body data
                      .toEitherT
                      .map { encryptedBody =>
                        result.copy(body = Enumerator(encryptedBody)) // Wrap it with Enumerator and copy result
                      }
                      .leftMap(_ => BadRequest("Encryption error")) // You will probably want proper error handling
                      .merge
                  }
              }
            .map(_.right)
          }
          .leftMap(_ => BadRequest("Encryption error"))
          .merge
      }
    }
}