10 changed files with 20 additions and 274 deletions
@ -0,0 +1,13 @@ |
|||||||
|
[[integrations]] |
||||||
|
= Integrations |
||||||
|
|
||||||
|
Spring Security provides integrations with numerous frameworks and APIs. |
||||||
|
In this section, we discuss generic integrations that are not specific to Servlet or Reactive environments. |
||||||
|
To see specific integrations, refer to the xref:servlet/integrations/index.adoc[Servlet] and xref:servlet/integrations/index.adoc[Reactive] Integrations sections. |
||||||
|
// FIXME add link to reactive integrations |
||||||
|
|
||||||
|
* xref:features/integrations/cryptography.adoc[Cryptography] |
||||||
|
* xref:features/integrations/data.adoc[Spring Data] |
||||||
|
* xref:features/integrations/concurrency.adoc[Java's Concurrency APIs] |
||||||
|
* xref:features/integrations/jackson.adoc[Jackson] |
||||||
|
* xref:features/integrations/localization.adoc[Localization] |
||||||
@ -1,264 +0,0 @@ |
|||||||
[[crypto]] |
|
||||||
= Spring Security Crypto Module |
|
||||||
|
|
||||||
|
|
||||||
[[spring-security-crypto-introduction]] |
|
||||||
== Introduction |
|
||||||
The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding. |
|
||||||
The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code. |
|
||||||
|
|
||||||
|
|
||||||
[[spring-security-crypto-encryption]] |
|
||||||
== Encryptors |
|
||||||
The Encryptors class provides factory methods for constructing symmetric encryptors. |
|
||||||
Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form. |
|
||||||
You can also construct TextEncryptors to encrypt text strings. |
|
||||||
Encryptors are thread-safe. |
|
||||||
|
|
||||||
[[spring-security-crypto-encryption-bytes]] |
|
||||||
=== BytesEncryptor |
|
||||||
Use the `Encryptors.stronger` factory method to construct a BytesEncryptor: |
|
||||||
|
|
||||||
.BytesEncryptor |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
Encryptors.stronger("password", "salt"); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
Encryptors.stronger("password", "salt") |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
The "stronger" encryption method creates an encryptor using 256 bit AES encryption with |
|
||||||
Galois Counter Mode (GCM). |
|
||||||
It derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2). |
|
||||||
This method requires Java 6. |
|
||||||
The password used to generate the SecretKey should be kept in a secure place and not be shared. |
|
||||||
The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised. |
|
||||||
A 16-byte random initialization vector is also applied so each encrypted message is unique. |
|
||||||
|
|
||||||
The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length. |
|
||||||
Such a salt may be generated using a KeyGenerator: |
|
||||||
|
|
||||||
.Generating a key |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
val salt = KeyGenerators.string().generateKey() // generates a random 8-byte salt that is then hex-encoded |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
Users may also use the `standard` encryption method, which is 256-bit AES in Cipher Block Chaining (CBC) Mode. |
|
||||||
This mode is not https://en.wikipedia.org/wiki/Authenticated_encryption[authenticated] and does not provide any |
|
||||||
guarantees about the authenticity of the data. |
|
||||||
For a more secure alternative, users should prefer `Encryptors.stronger`. |
|
||||||
|
|
||||||
[[spring-security-crypto-encryption-text]] |
|
||||||
=== TextEncryptor |
|
||||||
Use the Encryptors.text factory method to construct a standard TextEncryptor: |
|
||||||
|
|
||||||
.TextEncryptor |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
Encryptors.text("password", "salt"); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
Encryptors.text("password", "salt") |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
A TextEncryptor uses a standard BytesEncryptor to encrypt text data. |
|
||||||
Encrypted results are returned as hex-encoded strings for easy storage on the filesystem or in the database. |
|
||||||
|
|
||||||
Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor: |
|
||||||
|
|
||||||
.Queryable TextEncryptor |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
Encryptors.queryableText("password", "salt"); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
Encryptors.queryableText("password", "salt") |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling. |
|
||||||
The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated. |
|
||||||
This means the same text encrypted multiple times will always produce the same encryption result. |
|
||||||
This is less secure, but necessary for encrypted data that needs to be queried against. |
|
||||||
An example of queryable encrypted text would be an OAuth apiKey. |
|
||||||
|
|
||||||
[[spring-security-crypto-keygenerators]] |
|
||||||
== Key Generators |
|
||||||
The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators. |
|
||||||
Using this class, you can create a BytesKeyGenerator to generate byte[] keys. |
|
||||||
You can also construct a StringKeyGenerator to generate string keys. |
|
||||||
KeyGenerators are thread-safe. |
|
||||||
|
|
||||||
=== BytesKeyGenerator |
|
||||||
Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance: |
|
||||||
|
|
||||||
.BytesKeyGenerator |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
BytesKeyGenerator generator = KeyGenerators.secureRandom(); |
|
||||||
byte[] key = generator.generateKey(); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
val generator = KeyGenerators.secureRandom() |
|
||||||
val key = generator.generateKey() |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
The default key length is 8 bytes. |
|
||||||
There is also a KeyGenerators.secureRandom variant that provides control over the key length: |
|
||||||
|
|
||||||
.KeyGenerators.secureRandom |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
KeyGenerators.secureRandom(16); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
KeyGenerators.secureRandom(16) |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns the same key on every invocation: |
|
||||||
|
|
||||||
.KeyGenerators.shared |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
KeyGenerators.shared(16); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
KeyGenerators.shared(16) |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
=== StringKeyGenerator |
|
||||||
Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String: |
|
||||||
|
|
||||||
.StringKeyGenerator |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
KeyGenerators.string(); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
KeyGenerators.string() |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
[[spring-security-crypto-passwordencoders]] |
|
||||||
== Password Encoding |
|
||||||
The password package of the spring-security-crypto module provides support for encoding passwords. |
|
||||||
`PasswordEncoder` is the central service interface and has the following signature: |
|
||||||
|
|
||||||
[source,java] |
|
||||||
---- |
|
||||||
public interface PasswordEncoder { |
|
||||||
|
|
||||||
String encode(String rawPassword); |
|
||||||
|
|
||||||
boolean matches(String rawPassword, String encodedPassword); |
|
||||||
} |
|
||||||
---- |
|
||||||
|
|
||||||
The matches method returns true if the rawPassword, once encoded, equals the encodedPassword. |
|
||||||
This method is designed to support password-based authentication schemes. |
|
||||||
|
|
||||||
The `BCryptPasswordEncoder` implementation uses the widely supported "bcrypt" algorithm to hash the passwords. |
|
||||||
Bcrypt uses a random 16 byte salt value and is a deliberately slow algorithm, in order to hinder password crackers. |
|
||||||
The amount of work it does can be tuned using the "strength" parameter which takes values from 4 to 31. |
|
||||||
The higher the value, the more work has to be done to calculate the hash. |
|
||||||
The default value is 10. |
|
||||||
You can change this value in your deployed system without affecting existing passwords, as the value is also stored in the encoded hash. |
|
||||||
|
|
||||||
.BCryptPasswordEncoder |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
|
|
||||||
// Create an encoder with strength 16 |
|
||||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); |
|
||||||
String result = encoder.encode("myPassword"); |
|
||||||
assertTrue(encoder.matches("myPassword", result)); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
|
|
||||||
// Create an encoder with strength 16 |
|
||||||
val encoder = BCryptPasswordEncoder(16) |
|
||||||
val result: String = encoder.encode("myPassword") |
|
||||||
assertTrue(encoder.matches("myPassword", result)) |
|
||||||
---- |
|
||||||
==== |
|
||||||
|
|
||||||
The `Pbkdf2PasswordEncoder` implementation uses PBKDF2 algorithm to hash the passwords. |
|
||||||
In order to defeat password cracking PBKDF2 is a deliberately slow algorithm and should be tuned to take about .5 seconds to verify a password on your system. |
|
||||||
|
|
||||||
|
|
||||||
.Pbkdf2PasswordEncoder |
|
||||||
==== |
|
||||||
.Java |
|
||||||
[source,java,role="primary"] |
|
||||||
---- |
|
||||||
// Create an encoder with all the defaults |
|
||||||
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder(); |
|
||||||
String result = encoder.encode("myPassword"); |
|
||||||
assertTrue(encoder.matches("myPassword", result)); |
|
||||||
---- |
|
||||||
|
|
||||||
.Kotlin |
|
||||||
[source,kotlin,role="secondary"] |
|
||||||
---- |
|
||||||
// Create an encoder with all the defaults |
|
||||||
val encoder = Pbkdf2PasswordEncoder() |
|
||||||
val result: String = encoder.encode("myPassword") |
|
||||||
assertTrue(encoder.matches("myPassword", result)) |
|
||||||
---- |
|
||||||
==== |
|
||||||
Loading…
Reference in new issue