在application.conf中为Play 2.0 / anorm加密db密码

时间:2012-07-25 19:00:52

标签: database scala encryption playframework playframework-2.0

我不想将未加密的密码放在应用程序配置文件中。

这个问题:Encrypting db password in application.conf有一个很好的解决方案,但它只适用于Play 1.

有人知道适用于Play 2.0的解决方案吗?我在Scala版本的Play 2.0.2中使用了anorm。

3 个答案:

答案 0 :(得分:3)

所有努力都毫无意义。当我们在数据库中放入哈希密码是因为人类可以在他们的大脑中保留密码,并且他们的大脑不可读。它被称为非对称加密。

您所谈论的事情只能通过对称加密实现:程序在运行时具有密钥,并使用此密钥解密db密码。但是,存储使用密钥加密的数据库密码并且仍然可以公开使用此密钥的重点是什么? (对于Java源代码和编译类都是如此)。链条只有最薄弱的环节才有力量。

当机器必须连接到数据库时,它需要一个密码:我们以纯文本格式存储此密码,因为程序必须按原样使用,并且不需要人工输入。我们所能做的就是强制执行安全性是限制对此纯文本文件的访问,最终使用仅存储在管理员脑海中的密码来保护它(顺便说一下,管理员更可能将所有密码保存在数据库中,也许是主密码)。请注意,如果您使用上述播放插件,情况不会改变。

我想到的唯一另一件事是Play应用程序,它只在管理员输入数据库密码时连接到数据库(但实际上这只是一个思考练习)

答案 1 :(得分:3)

我知道它有点晚了但是对于这个问题并没有更新的讨论。我想按照documentation中的建议分享实际的解决方案(Play v.2.5.X),现在可以覆盖GuiceApplicationLoader来配置GuiceApplicationBuilder来处理初始配置

在新课程modules/ApplicationLoaderConfig.scala中:

import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
import javax.xml.bind.DatatypeConverter

import play.api.inject.guice._
import play.api.{ApplicationLoader, Configuration}

class ApplicationLoaderConfig extends GuiceApplicationLoader() {

  override def builder(context: ApplicationLoader.Context): GuiceApplicationBuilder = {

    // Decrypt secrets
    val decryptedConfig = context.initialConfiguration ++
      Configuration("config.to.descrypt.1" -> decryptDES(context.initialConfiguration.getString("config.to.descrypt.1").get)) ++
      Configuration("config.to.descrypt.2" -> decryptDES(context.initialConfiguration.getString("config.to.descrypt.2").get))

    initialBuilder
      .in(context.environment)
      .loadConfig(decryptedConfig)
      .overrides(overrides(context): _*)
  }

  private def decryptDES(secret: String): String = {
    val key = "12345678"
    val skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "DES")

    val cipher = Cipher.getInstance("DES/ECB/PKCS5Padding")
    cipher.init(Cipher.DECRYPT_MODE, skeySpec)

    new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(secret)))
  }
}

同时添加到application.config

play.application.loader = "modules.ApplicationLoaderConfig"

答案 2 :(得分:2)

感谢与Raffaele的讨论以及我自己对代码的调查,似乎Play 2.0不允许您加密数据库密码。

如果我错过了什么,请告诉我。

编辑:可以通过以下方式使用自定义数据库驱动程序来解决此问题:

// Just redirect everything to the delegate
class DelegatingDriver(delegate: Driver) extends Driver
{
  def connect(url: String, info: Properties) = delegate.connect(url, info)
  def acceptsURL(url: String) = delegate.acceptsURL(url)
  def getPropertyInfo(url: String, info: Properties) = delegate.getPropertyInfo(url, info)
  def getMajorVersion = delegate.getMajorVersion
  def getMinorVersion = delegate.getMinorVersion
  def jdbcCompliant() = delegate.jdbcCompliant()
}

// Replace password in properties with the decrypted one
class MyDecryptingDriver extends DelegatingDriver(Class.forName("<my.original.Driver>").newInstance().asInstanceOf[Driver])
{
  override def connect(url: String, info: Properties)= {
    // copy Properties
    val overriddenProperties= clone(info)   
    // override password property with the decrypted value
    Option(info.getProperty("password")).foreach(value => overriddenProperties.setProperty("password", decryptPassword(value)))
    super.connect(url, overriddenProperties)
  }

  def clone(orig: Properties)= {
    val result= new Properties()
    orig.propertyNames().map(_.asInstanceOf[String]).foreach(pName => result.setProperty(pName, orig.getProperty(pName)))
    result
  }

  def decryptPassword(encrypted: String)= ...
}

然后你用my.com.MyDecrypting驱动程序替换application.conf / db..driver。不完美但对我有用......