Spring Boot 使用属性文件,至少默认情况下,密码是明文的。是否有可能以某种方式隐藏/解密这些密码?
Spring Boot 使用属性文件,至少默认情况下,密码是明文的。是否有可能以某种方式隐藏/解密这些密码?
您可以使用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轻松配置它,可以使用其starter 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.north-47.com/knowledge-base/spring-boot-password-encryption-with-jasypt/
要在应用程序中使用加密的属性,只需像往常一样使用它,使用您喜欢的任何方法(Spring Boot将自动连接到魔法,但属性必须当然位于类路径中):
使用@Value
注解
@Value("${db.password}")
private String password;
或者使用环境变量
@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
export JASYPT_ENCRYPTOR_PASSWORD=supersecretz
使用 . setEnv.sh
执行该文件
使用 mvn spring-boot:run &
在后台运行应用程序
删除文件 setEnv.sh
使用以下命令取消设置先前的环境变量:unset JASYPT_ENCRYPTOR_PASSWORD
除了已经提出的解决方案之外,我还可以添加一种选项来配置外部Secrets Manager
,例如Vault。
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>
添加Vault配置属性:
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
作为环境变量传递。
请参阅此处的文档。
还有一个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();
}
}
使用 Vault 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) {
// …
}
}
更新:我注意到一些人对此进行了负面评价,所以我必须说,尽管这不是一个理想的解决方案,但在某些情况下,它能够起作用并且被接受。
当服务绑定到应用程序时,Cloudfoundry使用环境变量来注入凭据。更多信息请参见https://docs.cloudfoundry.org/devguide/services/application-binding.html
如果您的系统不是共享的,那么这种方法也是可以接受的,特别是在本地开发中。当然,更加安全的方式由@J-Alex在答案中进行了解释。
答案:
如果您想隐藏密码,最简单的解决方法就是在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);
注意: 设置环境变量后,您可能需要重新启动。 对于Windows操作系统:
有关更多信息,请参阅此文档。
Spring Cloud Config Server可以实现这种行为。使用JCE,您可以在服务器上设置一个密钥,并使用它来加密应用程序的属性。
http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html
除了流行的K8s、jasypt或vault解决方案外,还有Karmahostage。它使您能够执行以下操作:
@EncryptedValue("${application.secret}")
private String application;
如果你在使用Spring Boot环境下流行的Kubernetes(K8S)或OpenShift,那么有可能在运行时存储和检索应用程序属性。这种技术称为secrets。在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
我在Spring Boot应用程序中隐藏DB密码的解决方案application.properties已经实现here。
场景:在启动时从application.properties读取一些虚假密码并保存在全局Spring对象ConfigurableEnvironment中。在运行时,它将被编程方式替换为真实的DB密码。 真实密码将从另一个配置文件中读取,该文件保存在安全的项目外部位置。
不要忘记:使用以下方式从主类调用Bean:@Autowired
private SchedUtilility utl;
mvn -Djasypt.encryptor.password=supersecretz spring-boot:run
不会在ps
输出中显示密码,从而暴露密码吗? - Srki RakicJASYPT_ENCRYPTOR_PASSWORD
。 - Federico Piazza