如何在aes_encrypt中传入自定义密钥?Spring Boot密钥安全存储方案
Great question—hardcoding encryption keys directly in your Java classes is a major security red flag, since decompiling the class file would expose them instantly. Let’s walk through several secure, practical solutions for your Spring Boot + JPA/Hibernate + MySQL stack:
1. Use Spring Boot Configuration Files + SpEL Expressions
The simplest approach is to move your key to a Spring configuration file (like application.properties or application.yml) and reference it using Spring Expression Language (SpEL) in your @ColumnTransformer annotation.
Step 1: Add the key to your config file
In application.properties:
# Store your key here (make sure this file is NOT committed to version control!) mysql.encryption.key=YourStrongUniqueKey123!
Step 2: Reference the key in @ColumnTransformer
Update your entity field to use the SpEL placeholder:
@ColumnTransformer( write = "aes_encrypt(sensitive_column, '${mysql.encryption.key}')", read = "aes_decrypt(sensitive_column, '${mysql.encryption.key}')" ) @Column(name = "sensitive_column") private String sensitiveData;
Spring will automatically replace ${mysql.encryption.key} with the value from your config file at runtime.
2. Use Environment Variables (More Secure Than Config Files)
To avoid storing keys in plaintext config files entirely, use environment variables. This keeps keys out of your codebase and server files.
Step 1: Set the environment variable
On Linux/macOS:
export MYSQL_ENCRYPT_KEY="YourEvenStrongerKey!"
On Windows (Command Prompt):
set MYSQL_ENCRYPT_KEY=YourEvenStrongerKey!
Step 2: Reference the variable in your config file
In application.properties:
mysql.encryption.key=${MYSQL_ENCRYPT_KEY}
Your @ColumnTransformer annotation stays exactly the same as in the first method.
3. Encrypt Config File Values with Jasypt
If you must keep keys in config files, encrypt them using Jasypt so even if the config file leaks, the key remains unreadable.
Step 1: Add Jasypt dependency
Include the Jasypt Spring Boot starter in your pom.xml:
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.5</version> </dependency>
Step 2: Encrypt your key
Use Jasypt’s command-line tool to generate an encrypted version of your key:
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="YourSecretKey" password="MasterEncryptionPassword" algorithm=PBEWithMD5AndDES
Replace MasterEncryptionPassword with a secure master password (this should be stored in an environment variable, not a config file).
Step 3: Configure encrypted key in application.properties
# Master password from environment variable jasypt.encryptor.password=${JASYPT_MASTER_PASSWORD} # Encrypted key wrapped in ENC() mysql.encryption.key=ENC(your-encrypted-key-string-here)
Spring will automatically decrypt the key at runtime using the master password.
4. Custom Hibernate Attribute Converter (Alternative to @ColumnTransformer)
If you want more control over encryption logic (or prefer encrypting/decrypting in Java rather than MySQL), use a custom AttributeConverter. This lets you inject the key directly into the converter via Spring.
Example Converter Class
@Converter(autoApply = false) public class AesAttributeConverter implements AttributeConverter<String, String> { private final String encryptionKey; // Inject key from Spring environment public AesAttributeConverter(@Value("${mysql.encryption.key}") String encryptionKey) { this.encryptionKey = encryptionKey; } @Override public String convertToDatabaseColumn(String attribute) { // Implement AES encryption logic here try { Cipher cipher = Cipher.getInstance("AES"); SecretKeySpec keySpec = new SecretKeySpec(encryptionKey.getBytes(StandardCharsets.UTF_8), "AES"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); return Base64.getEncoder().encodeToString(cipher.doFinal(attribute.getBytes(StandardCharsets.UTF_8))); } catch (Exception e) { throw new RuntimeException("Failed to encrypt data", e); } } @Override public String convertToEntityAttribute(String dbData) { // Implement AES decryption logic here try { Cipher cipher = Cipher.getInstance("AES"); SecretKeySpec keySpec = new SecretKeySpec(encryptionKey.getBytes(StandardCharsets.UTF_8), "AES"); cipher.init(Cipher.DECRYPT_MODE, keySpec); return new String(cipher.doFinal(Base64.getDecoder().decode(dbData)), StandardCharsets.UTF_8); } catch (Exception e) { throw new RuntimeException("Failed to decrypt data", e); } } }
Use the Converter in Your Entity
@Convert(converter = AesAttributeConverter.class) @Column(name = "sensitive_column") private String sensitiveData;
Critical Security Best Practices
- Never commit keys to version control: Add
application.properties/application.ymlto your.gitignorefile. - Use a secrets manager in production: For enterprise-grade security, use tools like HashiCorp Vault, AWS KMS, or Azure Key Vault to store and retrieve keys dynamically.
- Rotate keys regularly: Set up a process to rotate encryption keys periodically to minimize risk if a key is compromised.
- Encrypt database connections: Always use SSL/TLS for your MySQL connection to prevent key exposure during transit.
内容的提问来源于stack exchange,提问作者Abhijeet Saxena

