Spring Security 加密模块
Spring Security Crypto 模块提供了对称加密、密钥生成和密码编码的支持。该代码作为核心模块的一部分进行分发,但不依赖于任何其他 Spring Security(或 Spring)代码。
加密器
Encryptors 类提供了用于构建对称加密器的工厂方法。此类允许你创建 BytesEncryptor 实例,以加密原始 byte[]
形式的数据。你还可以构造 TextEncryptor 实例来加密文本字符串。加密器是线程安全的。
BytesEncryptor
和 TextEncryptor
都是接口。BytesEncryptor
有多个实现。
BytesEncryptor
你可以使用 Encryptors.stronger
工厂方法来构造一个 BytesEncryptor
:
- Java
- Kotlin
Encryptors.stronger("password", "salt");
Encryptors.stronger("password", "salt")
stronger
加密方法通过使用 256 位 AES 加密与 Galois Counter Mode (GCM) 来创建加密器。它通过使用 PKCS #5 的 PBKDF2(基于密码的密钥导出函数 #2)来推导密钥。此方法需要 Java 6。用于生成 SecretKey
的密码应保存在安全的地方,并且不应共享。盐用于防止在你的加密数据被泄露时对密钥进行字典攻击。还会应用一个 16 字节的随机初始化向量,以使每条加密消息都是唯一的。
所提供的的盐应该是十六进制编码的字符串形式,应是随机的,并且长度至少为 8 字节。你可以使用 KeyGenerator
生成这样的盐:
- Java
- Kotlin
String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded
val salt = KeyGenerators.string().generateKey() // generates a random 8-byte salt that is then hex-encoded
你也可以使用 standard
加密方法,该方法是采用密码块链(CBC)模式的256位AES。此模式未经过认证,不提供关于数据真实性的任何保证。为了更安全的选择,请使用 Encryptors.stronger
。
TextEncryptor
你可以使用 Encryptors.text
工厂方法来构造一个标准的 TextEncryptor:
- Java
- Kotlin
Encryptors.text("password", "salt");
Encryptors.text("password", "salt")
TextEncryptor
使用标准的 BytesEncryptor
来加密文本数据。加密结果以十六进制编码的字符串形式返回,以便于在文件系统或数据库中存储。
密钥生成器
KeyGenerators
类提供了许多便捷的工厂方法来构建不同类型的密钥生成器。通过使用此类,您可以创建一个 BytesKeyGenerator
来生成 byte[]
密钥。您还可以构建一个 StringKeyGenerator
来生成字符串密钥。KeyGenerators
是一个线程安全的类。
BytesKeyGenerator
你可以使用 KeyGenerators.secureRandom
工厂方法来生成一个由 SecureRandom
实例支持的 BytesKeyGenerator
:
- Java
- Kotlin
BytesKeyGenerator generator = KeyGenerators.secureRandom();
byte[] key = generator.generateKey();
val generator = KeyGenerators.secureRandom()
val key = generator.generateKey()
默认的密钥长度是 8 字节。KeyGenerators.secureRandom
变体提供了对密钥长度的控制:
- Java
- Kotlin
KeyGenerators.secureRandom(16);
KeyGenerators.secureRandom(16)
使用 KeyGenerators.shared
工厂方法来构建一个每次都返回相同密钥的 BytesKeyGenerator:
KeyGenerators.shared()
- Java
- Kotlin
KeyGenerators.shared(16);
KeyGenerators.shared(16)
StringKeyGenerator
你可以使用 KeyGenerators.string
工厂方法来构造一个 8 字节的 SecureRandom
KeyGenerator
,它会将每个密钥以十六进制编码为 String
:
- Java
- Kotlin
KeyGenerators.string();
KeyGenerators.string()
密码编码
spring-security-crypto
模块的 password 包提供了对密码编码的支持。PasswordEncoder
是核心的服务接口,具有以下签名:
public interface PasswordEncoder {
String encode(CharSequence rawPassword);
boolean matches(CharSequence rawPassword, String encodedPassword);
default boolean upgradeEncoding(String encodedPassword) {
return false;
}
}
matches
方法在 rawPassword
经过编码后等于 encodedPassword
时返回 true。此方法旨在支持基于密码的认证方案。
BCryptPasswordEncoder
实现使用广泛支持的“bcrypt”算法来对密码进行哈希处理。Bcrypt 使用一个随机的 16 字节盐值,并且是一种故意设计得很慢的算法,以阻碍密码破解者。你可以通过使用 strength
参数来调整其工作量,该参数的取值范围为 4 到 31。值越高,计算哈希所需的工作量就越大。默认值为 10
。你可以在部署的系统中更改此值,而不会影响现有的密码,因为该值也会存储在编码后的哈希中。以下示例使用了 BCryptPasswordEncoder
:
- Java
- Kotlin
// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// Create an encoder with strength 16
val encoder = BCryptPasswordEncoder(16)
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
Pbkdf2PasswordEncoder
实现使用 PBKDF2 算法来对密码进行哈希处理。为了抵御密码破解,PBKDF2 是一种故意设计得很慢的算法,并且应该调整为在你的系统上验证一个密码大约需要 .5 秒。以下系统使用了 Pbkdf2PasswordEncoder
:
- Java
- Kotlin
// Create an encoder with all the defaults
Pbkdf2PasswordEncoder encoder = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// Create an encoder with all the defaults
val encoder = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))