Criptografando a senha do banco de dados em application.conf para Play 2.0/anorm
-
11-12-2019 - |
Pergunta
Não quero colocar senhas não criptografadas no arquivo de configuração do aplicativo.
Essa questão: Criptografando a senha do banco de dados em application.conf tem uma ótima solução para o problema, mas funciona apenas para o Play 1.
Alguém conhece uma solução que funcione para o Play 2.0?Estou usando anorm na versão Scala do Play 2.0.2.
Solução 3
Graças à discussão com Raffaele e seguindo minha própria investigação do código, parece que o Play 2.0 não permite criptografar senhas de banco de dados.
Se eu perdi alguma coisa, por favor me avise.
EDITAR:Pode-se contornar o problema usando o driver de banco de dados personalizado da seguinte maneira:
// 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)= ...
}
então você substitui application.conf/db..driver pelo driver my.com.MyDecrypting.Não é perfeito, mas funciona para mim...
Outras dicas
Todos os esforços são inúteis. Quando colocamos a senha do Hashed em um banco de dados é porque os humanos podem reter senhas em seus cérebros, e seus cérebros não são legíveis . É chamado criptografia assimétrica .
A coisa que você está falando só é possível com Simétrica Criptografia: O programa tem a chave no tempo de execução e usa essa chave para descriptografar a senha do banco de dados. Mas qual é o ponto de armazenar a senha do banco de dados criptografada com uma chave, e ainda assim ter essa chave disponível publicamente? (Isso é verdade para fontes Java e classes compiladas). Uma corrente é tão forte quanto sua ligação mais fraca.
Quando uma máquina precisa se conectar a um dB, ele precisa de uma senha: Nós armazenamos essa senha em texto simples porque o programa deve usá-lo como é, e nenhuma entrada humana é necessária . Tudo o que podemos fazer para impor a segurança é restringir o acesso a este arquivo de texto simples, eventualmente protegendo-o com uma senha armazenada apenas na mente do administrador (BTW, mais provável que o administrador mantenha todas as suas senhas em um banco de dados, talvez com um senha mestra). Note que as coisas não mudam se você usar o plugin mencionado.
A única outra coisa que vem à minha mente é um aplicativo de reprodução que só se conecta ao banco de dados quando o administrador entrou na senha do banco de dados (mas realmente este é apenas um exercício de pensamento)
Eu sei que é um pouco tarde, mas não há discussões mais recentes sobre esse problema.Quero compartilhar a solução real (Play v.2.5.X), conforme sugerido em documentação, agora é possível substituir o GuiceApplicationLoader
para configurar o GuiceApplicationBuilder
para processar de alguma forma as configurações iniciais.
Em uma nova aula 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)))
}
}
Adicione também a application.config
:
play.application.loader = "modules.ApplicationLoaderConfig"