2

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

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

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

4

3 回答 3

3

所有的努力都是徒劳的。当我们将哈希密码放入数据库时​​,是因为人类可以将密码保留在他们的大脑中,而他们的大脑是不可读的。它被称为非对称加密。

您正在谈论的事情只能通过对称加密实现:程序在运行时拥有密钥,并使用此密钥解密数据库密码。但是,存储使用密钥加密的数据库密码并仍然让该密钥公开可用有什么意义呢?(对于 java 源代码和编译的类都是如此)。链条的强度取决于其最薄弱的环节。

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

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

于 2012-07-25T21:35:47.327 回答
3

我知道这有点晚了,但没有关于这个问题的新讨论。我想分享实际的解决方案(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"
于 2016-04-21T17:00:08.167 回答
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)= ...
}

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

于 2012-07-27T18:00:31.240 回答