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 详细解释一下 @FedericoPiazzamvn -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 Boot Actuator 隐藏 env 端点中的属性值
如何使用 Spring Boot 和 Angular 应用程序隐藏授权标头
Docker 和 Spring Boot:如何从 url 隐藏端口?
java - 如何使用SpringJUnit4TestRunner在junit测试中隐藏spring boot banner.txt?