正在application.conf中加密数据库密码,适用于Play 2.0/anorm



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

这个问题:在application.conf中加密数据库密码有一个很好的解决方案,但它只适用于Play 1。

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

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

您所说的事情只有在对称加密的情况下才可能发生:程序在运行时拥有密钥,并使用该密钥解密数据库密码。但是,存储用密钥加密的数据库密码,并公开该密钥有什么意义呢?(对于java源代码和编译后的类都是如此)。一条链条只有最薄弱的环节才有力量。

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

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

我知道时间有点晚了,但没有关于这个问题的新讨论。我想分享实际的解决方案(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"

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

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

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

// 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。不完美,但适用于我…

最新更新