Spring Boot sử dụng tệp thuộc tính và ít nhất theo mặc định, mật khẩu ở dạng văn bản thuần túy. Có thể ẩn / giải mã chúng bằng cách nào đó không?
Spring Boot sử dụng tệp thuộc tính và ít nhất theo mặc định, mật khẩu ở dạng văn bản thuần túy. Có thể ẩn / giải mã chúng bằng cách nào đó không?
Câu trả lời:
Bạn có thể sử dụng Jasypt để mã hóa các thuộc tính, vì vậy bạn có thể có thuộc tính của mình như sau:
db.password=ENC(XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=)
Jasypt cho phép bạn mã hóa các thuộc tính của mình bằng các thuật toán khác nhau, sau khi bạn có được thuộc tính được mã hóa mà bạn đặt bên trong ENC(...)
. Ví dụ: bạn có thể mã hóa theo cách này thông qua Jasypt bằng cách sử dụng thiết bị đầu cuối:
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=
Để dễ dàng cấu hình nó với Spring Boot, bạn có thể sử dụng bộ khởi động jasypt-spring-boot-starter với ID nhómcom.github.ulisesbocchio
Hãy nhớ rằng bạn sẽ cần khởi động ứng dụng của mình bằng chính mật khẩu bạn đã sử dụng để mã hóa các thuộc tính. Vì vậy, bạn có thể khởi động ứng dụng của mình theo cách này:
mvn -Djasypt.encryptor.password=supersecretz spring-boot:run
Hoặc sử dụng biến môi trường (nhờ liên kết thư giãn khởi động lò xo):
export JASYPT_ENCRYPTOR_PASSWORD=supersecretz
mvn spring-boot:run
Bạn có thể kiểm tra liên kết dưới đây để biết thêm chi tiết:
https://www.ricston.com/blog/encrypting-properties-in-spring-boot-with-jasypt-spring-boot/
Để sử dụng các thuộc tính được mã hóa trong ứng dụng của bạn, chỉ cần sử dụng nó như bình thường, sử dụng một trong hai phương pháp bạn thích (Spring Boot kết nối điều kỳ diệu, dù sao thì thuộc tính tất nhiên phải nằm trong classpath):
Sử dụng @Value
chú thích
@Value("${db.password}")
private String password;
Hoặc sử dụng Environment
@Autowired
private Environment environment;
public void doSomething(Environment env) {
System.out.println(env.getProperty("db.password"));
}
Cập nhật: cho môi trường sản xuất, để tránh lộ mật khẩu trong dòng lệnh, vì bạn có thể truy vấn các quy trình với ps
, các lệnh trước đó với history
, v.v. Bạn có thể:
touch setEnv.sh
setEnv.sh
để xuất JASYPT_ENCRYPTOR_PASSWORD
biến
#! / bin / bash
xuất JASYPT_ENCRYPTOR_PASSWORD = supersecretz
. setEnv.sh
mvn spring-boot:run &
setEnv.sh
unset JASYPT_ENCRYPTOR_PASSWORD
mvn -Djasypt.encryptor.password=supersecretz spring-boot:run
hiển thị trong ps
đầu ra, lộ mật khẩu sao?
JASYPT_ENCRYPTOR_PASSWORD
CẬP NHẬT: Tôi nhận thấy mọi người bỏ phiếu cho điều này, vì vậy tôi phải nói rằng mặc dù đây không phải là một giải pháp lý tưởng, nhưng điều này hoạt động và có thể chấp nhận được trong một số trường hợp sử dụng. Cloudfoundry sử dụng các biến Môi trường để đưa thông tin xác thực khi Dịch vụ được liên kết với một ứng dụng. Thông tin thêm https://docs.cloudfoundry.org/devguide/services/application-binding.html
Và cũng như nếu hệ thống của bạn không được chia sẻ, thì đối với sự phát triển cục bộ, điều này cũng có thể chấp nhận được. Tất nhiên, cách an toàn và bảo mật hơn được giải thích trong Trả lời của @ J-Alex.
Câu trả lời:
Nếu bạn muốn ẩn mật khẩu của mình thì giải pháp đơn giản nhất là sử dụng các biến Môi trường trong application.properties
tệp hoặc trực tiếp trong mã của bạn.
Trong application.properties
:
mypassword=${password}
Sau đó, trong lớp cấu hình của bạn:
@Autowired
private Environment environment;
[...]//Inside a method
System.out.println(environment.getProperty("mypassword"));
Trong configuration
lớp học của bạn :
@Value("${password}")
private String herokuPath;
[...]//Inside a method
System.out.println(herokuPath);
Lưu ý: Bạn có thể phải khởi động lại sau khi đặt biến môi trường. Cho cửa sổ:
Tham khảo Tài liệu này để biết thêm thông tin.
Máy chủ cấu hình đám mây mùa xuân sẽ cho phép loại hành vi này. Sử dụng JCE, bạn có thể thiết lập một khóa trên máy chủ và sử dụng nó để mã hóa các thuộc tính ứng dụng.
http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html
Đối với các giải pháp đã được đề xuất, tôi có thể thêm một tùy chọn để định cấu hình bên ngoài Secrets Manager
chẳng hạn như Vault .
vault server -dev
( Chỉ dành cho DEV và không dành cho PROD )vault write secret/somename key1=value1 key2=value2
vault read secret/somename
Thêm phần phụ thuộc sau vào dự án SpringBoot của bạn:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-vault-config</artifactId>
</dependency>
Thêm thuộc tính cấu hình 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}
Truyền VAULT_TOKEN
như một biến môi trường.
Tham khảo tài liệu tại đây.
Có một dự án Spring Vault cũng có thể được sử dụng để truy cập, lưu trữ và thu hồi các bí mật.
Sự phụ thuộc:
<dependency>
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
</dependency>
Định cấu hình Mẫu Vault:
@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {
@Override
public VaultEndpoint vaultEndpoint() {
return new VaultEndpoint();
}
@Override
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication("…");
}
}
Tiêm và sử dụng 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();
}
}
Sử dụng Vault PropertySource
:
@VaultPropertySource(value = "aws/creds/s3",
propertyNamePrefix = "aws."
renewal = Renewal.RENEW)
public class Config {
}
Ví dụ sử dụng:
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) {
// …
}
}
Trong trường hợp bạn đang sử dụng khá phổ biến trong môi trường Spring Boot Kubernetes (K8S) hoặc OpenShift, có khả năng lưu trữ và truy xuất các thuộc tính của ứng dụng trong thời gian chạy. Kỹ thuật này được gọi là bí mật . Trong tệp yaml cấu hình của bạn cho Kubernetes hoặc OpenShift, bạn khai báo biến và trình giữ chỗ cho nó và ở phía K8S \ OpenShift khai báo giá trị thực tương ứng với trình giữ chỗ này. Để biết chi tiết triển khai, hãy xem: K8S: https://kubernetes.io/docs/concept/configuration/secret/ OpenShift: https://docs.openshift.com/container-platform/3.11/dev_guide/secrets.html
Giải pháp của tôi để che giấu một DB-mật khẩu trong mùa xuân Boot App của application.properties không thực hiện ở đây .
Tình huống: một số mật khẩu giả đã được đọc và lưu từ application.properties khi bắt đầu, trong đối tượng Spring toàn cầu ConfigurableEn Môi trường sẽ được, trong Run-Time được thay thế lập trình bằng DB-Password thực. Mật khẩu thực sẽ được đọc từ một tệp cấu hình khác, được lưu ở nơi an toàn, bên ngoài dự án.
Đừng quên: gọi Bean từ lớp chính bằng:
@Autowired
private SchedUtilility utl;
Ngoài các giải pháp K8s, jasypt hoặc vault phổ biến, còn có Karmahostage . Nó cho phép bạn làm:
@EncryptedValue("${application.secret}")
private String application;
Nó hoạt động giống như cách jasypt làm, nhưng mã hóa xảy ra trên một giải pháp saas chuyên dụng, với một mô hình ACL chi tiết hơn được gắn vào nó.