Spring Boot如何在属性文件中隐藏密码

Posted

技术标签:

【中文标题】Spring Boot如何在属性文件中隐藏密码【英文标题】:Spring Boot how to hide passwords in properties file 【发布时间】:2016-09-21 03:26:33 【问题描述】:

Spring Boot 使用属性文件,至少默认情况下,密码是纯文本的。是否有可能以某种方式隐藏/解密这些?

【问题讨论】:

【参考方案1】:

Spring Cloud Config Server 将允许这种类型的行为。使用 JCE,您可以在服务器上设置一个密钥并使用它来加密应用程序属性。

http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html

【讨论】:

【参考方案2】:

更新:我注意到人们对此投了反对票,所以我不得不说,虽然这不是一个理想的解决方案,但在某些用例中这是可行的并且可以接受。 当服务绑定到应用程序时,Cloudfoundry 使用环境变量注入凭据。更多信息https://docs.cloudfoundry.org/devguide/services/application-binding.html

如果你的系统不是共享的,那么对于本地开发来说这也是可以接受的。当然,更安全可靠的方式在@J-Alex 的Answer 中进行了说明。

答案:

如果您想隐藏您的密码,那么最简单的解决方案是在application.properties 文件中或直接在您的代码中使用环境变量

application.properties:

mypassword=$password

然后在你的配置类中:

@Autowired
private Environment environment;

[...]//Inside a method
System.out.println(environment.getProperty("mypassword"));

在您的configuration 班级中:

@Value("$password")
private String herokuPath;

[...]//Inside a method
System.out.println(herokuPath);

注意:设置环境变量后可能需要重新启动。 对于窗户:

请参阅此Documentation 了解更多信息。

【讨论】:

我认为在环境变量中设置主密码不是一个好主意。密码现在比必要的更暴露。与在环境中设置它相比,为它提供一个如 Federico 所示的初创公司更少暴露且更“安全”。 是的,如果您使用的是共享计算机,则不会。但是,如果您是计算机的唯一管理员,则其他用户无法看到环境变量。我回答了隐藏的部分和更容易的部分。但是,是的,我同意 Federico 建议的方法要好得多。 请看:diogomonica.com/2017/03/27/… @Jaavaaan 在环境变量中提供 JASYPT_ENCRYPTOR_PASSWORD 以解码数据库密码与此答案同样不安全。 @Jaavaaan 请阅读更新。我已经提到这在所有情况下都不是安全的,但是有像 CF 这样的有效用例。还指出了使用 HashiCorp Vault 的更好的高度安全的解决方案。【参考方案3】:

您可以使用 Jasypt 来加密属性,因此您可以拥有这样的属性:

db.password=ENC(XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=)

Jasypt 允许您使用不同的算法加密您的属性,一旦您获得了放入 ENC(...) 中的加密属性。例如,您可以使用终端通过 Jasypt 以这种方式加密:

encrypted-pwd$ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar  org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="contactspassword" password=supersecretz algorithm=PBEWithMD5AndDES

----ENVIRONMENT-----------------

Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 24.45-b08



----ARGUMENTS-------------------

algorithm: PBEWithMD5AndDES
input: contactspassword
password: supersecretz



----OUTPUT----------------------

XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=

要使用 Spring Boot 轻松配置它,您可以使用其启动器 jasypt-spring-boot-starter 和组 ID com.github.ulisesbocchio

请记住,您需要使用与加密属性相同的密码来启动您的应用程序。所以,你可以这样启动你的应用:

mvn -Djasypt.encryptor.password=supersecretz spring-boot:run

或者使用环境变量(感谢 spring boot 宽松绑定):

export JASYPT_ENCRYPTOR_PASSWORD=supersecretz
mvn spring-boot:run

您可以查看以下链接了解更多详情:

https://www.ricston.com/blog/encrypting-properties-in-spring-boot-with-jasypt-spring-boot/

要在您的应用程序中使用您的加密属性,只需像往常一样使用它,使用您喜欢的任何一种方法(Spring Boot 具有魔力,无论如何属性当然必须在类路径中):

使用@Value注解

@Value("$db.password")
private String password;

或者使用Environment

@Autowired
private Environment environment;

public void doSomething(Environment env) 
    System.out.println(env.getProperty("db.password"));

更新:对于生产环境,为了避免在命令行中暴露密码,因为您可以使用ps查询进程,使用history等查询之前的命令。您可以:

创建这样的脚本:touch setEnv.sh 编辑setEnv.sh 以导出JASYPT_ENCRYPTOR_PASSWORD 变量

#!/bin/bash

导出 JASYPT_ENCRYPTOR_PASSWORD=supersecretz

. setEnv.sh执行文件 使用mvn spring-boot:run & 在后台运行应用程序 删除文件setEnv.sh 取消设置之前的环境变量:unset JASYPT_ENCRYPTOR_PASSWORD

【讨论】:

能否请您使用 gradle @Ferica Piazza 详细解释一下 @FedericoPiazza mvn -Djasypt.encryptor.password=supersecretz spring-boot:run 不会出现在ps 输出中,暴露密码吗? @SrkiRakic 是的,当然。这仅用于开发,如果您希望将其用于生产,则应使用环境变量。 Spring boot 允许你使用JASYPT_ENCRYPTOR_PASSWORD 哈哈,它是如何进入环境变量的?可能来自另一个文件,例如服务定义:D jasypt 在密码派生方面也已过时,因此请确保使用完全随机的 32 个字符的密码 @ChrisF 我认为您误解了加密的工作原理。 input="this is the text I want to encrypt"password="this is the key used to encrypt the input"【参考方案4】:

对于已经提出的解决方案,我可以添加一个选项来配置外部Secrets Manager,例如Vault。

    配置 Vault Server vault server -dev仅适用于 DEV,不适用于 PROD) 写秘密vault write secret/somename key1=value1 key2=value2 验证秘密vault read secret/somename

将以下依赖项添加到您的 SpringBoot 项目中:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-vault-config</artifactId>
</dependency>

添加保险柜配置属性:

spring.cloud.vault.host=localhost
spring.cloud.vault.port=8200
spring.cloud.vault.scheme=http
spring.cloud.vault.authentication=token
spring.cloud.vault.token=$VAULT_TOKEN

VAULT_TOKEN 作为环境变量传递。

参考文档here.

有一个Spring Vault 项目也可用于访问、存储和撤销机密。

依赖:

<dependency>
    <groupId>org.springframework.vault</groupId>
    <artifactId>spring-vault-core</artifactId>
</dependency>

配置 Vault 模板:

@Configuration
class VaultConfiguration extends AbstractVaultConfiguration 

  @Override
  public VaultEndpoint vaultEndpoint() 
    return new VaultEndpoint();
  

  @Override
  public ClientAuthentication clientAuthentication() 
    return new TokenAuthentication("…");
  

注入和使用VaultTemplate:

public class Example 

  @Autowired
  private VaultOperations operations;

  public void writeSecrets(String userId, String password) 
      Map<String, String> data = new HashMap<String, String>();
      data.put("password", password);
      operations.write(userId, data);
  

  public Person readSecrets(String userId) 
      VaultResponseSupport<Person> response = operations.read(userId, Person.class);
      return response.getBody();
  

使用保险柜PropertySource

@VaultPropertySource(value = "aws/creds/s3",
  propertyNamePrefix = "aws."
  renewal = Renewal.RENEW)
public class Config 


使用示例:

public class S3Client 

  // inject the actual values
  @Value("$aws.access_key")
  private String awsAccessKey;
  @Value("$aws.secret_key")
  private String awsSecretKey;

  public InputStream getFileFromS3(String filenname) 
    // …
  

【讨论】:

这个解决方案+1。使用像 vault / etcd(或任何其他)这样的系统是要走的路。 diogomonica.com/2017/03/27/… -1 因为这并不能解释如何保护“主”密钥 (VAULT_TOKEN)。 VAULT_TOKEN 环境变量从何而来?它是如何保护的?在不保护该密钥的情况下,攻击者可以使用它使用 Spring Boot jar 中打包的代码从保管库中检索秘密。 保护 prod 也是主要问题。所以,这里不得不说。开发/质量保证环境指南(如果可以的话)。 这在有很多密码时有效。它适用于一个密码进行连接,但将保险库密码放入环境中很有趣,因此您不必将另一个密码放入同一环境中。 为什么我们只想用于开发?产品很重要。【参考方案5】:

如果您在 Spring Boot 环境中使用非常流行的 Kubernetes (K8S) 或 OpenShift,则可以在运行时存储和检索应用程序属性。这种技术称为秘密。在 Kubernetes 或 OpenShift 的配置 yaml 文件中,您为其声明变量和占位符,并在 K8S\OpenShift 端声明与此占位符对应的实际值。 实现细节见: K8S:https://kubernetes.io/docs/concepts/configuration/secret/ OpenShift:https://docs.openshift.com/container-platform/3.11/dev_guide/secrets.html

【讨论】:

【参考方案6】:

我在 Spring Boot App 的 application.properties 中隐藏 DB-Password 的解决方案确实实现了 here。

场景:一些假密码已经在启动时从application.properties 读取并保存,在全局 Spring 对象 ConfigurableEnvironment 中,将在运行时以编程方式替换为真正的 DB-Password。 真正的密码将从另一个配置文件中读取,保存在安全的项目外部位置。

不要忘记:从main class 调用Bean 使用:

@Autowired
private SchedUtilility utl;

【讨论】:

【参考方案7】:

除了流行的 K8s、jasypt 或 vault 解决方案之外,还有Karmahostage。它使您能够:

@EncryptedValue("$application.secret")
private String application;

它的工作方式与 jasypt 相同,但加密发生在专用 saas 解决方案上,并附加了更细粒度的 ACL 模型。

【讨论】:

以上是关于Spring Boot如何在属性文件中隐藏密码的主要内容,如果未能解决你的问题,请参考以下文章

spring security ldap隐藏密码属性

Spring Boot Actuator 隐藏 env 端点中的属性值

在spring xml文件中隐藏数据源密码

如何使用 Spring Boot 和 Angular 应用程序隐藏授权标头

Docker 和 Spring Boot:如何从 url 隐藏端口?

java - 如何使用SpringJUnit4TestRunner在junit测试中隐藏spring boot banner.txt?