1. PasswordEncoder 계약
1) 정의
계약을 구현해 스프링 시큐리티에 사용자 암호를 검증하는 방법을 알려줄 수 있음
인증 프로세스에서 암호가 유효한지를 확인
2) 인터페이스 코드로 계약 구현
public interface PasswordEncoder {
String encode(CharSequence rawPassword);
boolean matches(CharSequence rawPassword, String encodedPassword);
default boolean upgradeEncoding(String encodedPassword){
return false;
}
}
encode 및 matches 메서드는 계약의 책임을 정의
encode
- 주어진 문자열을 변환해 반환
- 암호화 수행
matches
- 인코딩된 문자열이 원시 암호와 일치하는지 나중에 확인
- 지정된 암호를 인증 프로세스에서 알려진 자격 증명의 집합을 대상으로 비교
- encode 메서드에서 반환된 문자열은 항상 같은 PasswordEncoder의 matches 메서드로 검증할 수 있어야 함
upgradeEncoding
- true를 반환하도록 메서드를 재정의하면 인코딩된 암호를 보안 향상을 위해 다시 인코딩
2. PasswordEncoder 구현 옵션
1) NoOpPasswordEncoder
- 암호를 인코딩하지 않고 일반 텍스트로 유지.
- 이 구현은 예제 용도로만 적당하며 암호를 해시하지 않기 때문에 실제에서는 절대 쓰지 말아야 함
2) StandardPasswordEncoder
- SHA-256을 이용해 암호를 해시
- 해싱 프로세스에 적용할 비밀을 지정할 수 있음
- 강도가 약한 해싱 알고리즘을 사용하는 구식이라 새 구현에는 쓰면 안 좋음
3) Pbkdf2PasswordEncoder
- PBKDF2를 이용
- 반복 횟수 인수만큼 HMAC를 수행하는 단순하고 느린 해싱 함수
- 인코딩 프로세스에 이용되는 키의 값, 암호 인코딩의 반복 횟수, 해시의 크기를 매개 변수로 받음
- 해시가 길수록 암호가 강력해지지만 성능이 안 좋아짐
- 반복횟수를 늘리면 암호가 강력해지지만 애플리케이션이 소비하는 리소스가 증가해서 성능이 안 좋아짐
4) BCryptPasswordEncoder
- bcrypt 강력 해싱 함수로 암호를 인코딩
- 인코딩 프로세스에 이용되는 로그 라운드를 나타내는 강도 계수 지정 가능, 로그 라운드는 해싱 작업이 이용하는 반복 횟수에 영향을 줌
- 인코딩에 이용되는 SecureRandom 인스턴스 변경 가능
5) SCryptPasswordEncoder
- scrypt 해싱 함수로 암호를 인코딩
- cpu비용, 메모리 비용, 병렬화 계수, 키 길이, 솔트 길이를 매개변수로 받을 수 있음
3. DelegatingPasswordEncoder
1) 개념
다양한 암호 인코더를 갖추고 특정 구성에 따라 선택하는 방식을 지원
2) 방법
- 다양한 암호 인코더의 접두사와 인스턴스를 맵에 저장하고 들어오는 접두사에 맞는 인코더를 리턴해서 구현을 위임
- 스프링 시큐리티는 편의를 위해 모든 표준 제공 PasswordEncoder의 구현에 대한 맵을 가진 DelegatingPasswordEncoder를 생성하는 방법을 제공함
- PasswordEncoderFactories 클래스에는 bcrypt가 기본 인코더인 DelegatingPasswordEncoder의 구현을 반환하는 정적 메서드 createDelegatingPasswordEncoder가 있음
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
4. 키 생성기
1) 개념
특정한 종류의 키를 생성하는 객체로서 일반적으로 암호화나 해싱 알고리즘에 필요
2) 종류
BytesKeyGenerator
- 팩터리 클래스 KeyGenerators로 직접 만들 수 있음
- 8바이트 길이의 키를 생성
BytesKeyGenerator keyGenerator = KeyGenerators.secureRandom();
byte [] key = keyGenerator.generateKey();
int keyLength = keyGenerator.getKey();
// 같은 키 생성기를 호출하면 같은 키 값을 반환하는 구현
BytesKeyGenerator keyGenerator = KeyGenerators.shared(16);
byte [] key1 = keyGenerator.generateKey();
byte [] key2 = keyGenerator.generateKey();
StringKeyGenerator
- 팩터리 클래스 KeyGenerators로 직접 만들 수 있음
- 문자열 키를 얻을 수 있음
- 생성된 키는 보통 해싱 또는 암호화 알고리즘의 솔트 값으로 이용됨
- 8바이트 키를 생성하고 이를 16진수 문자열로 인코딩
StringKeyGenerator keyGenerator = KeyGenerators.string();
String salt = keyGenerator.generateKey();
5. 암호기
1) 개념
데이터를 암호화 및 복호화하는 객체
2) 종류
BytesEncryptor
바이트 배열로 입력 데이터를 받음
Encryptors.standard()
- 256바이트 AES 암호화를 이용해 입력 암호화
Encryptors.stronger()
- standard보다 더 강력한 바이트 암호기 인스턴스를 만듦
String salt = KeyGenerators.string().generateKey();
String password = "secret";
String valueToEncrypt = "HELLO";
BytesEncryptor e = Encryptors.standard(password, salt);
byte [] encrypted = e.encrypt(valueToEncrypt.getBytes());
byte [] decrypted = e.decrypt(encrypted);
// 암호기 종류
BytesEncryptor e = Encryptors.standard(password, salt);
BytesEncryptor e = Encryptors.stronger(password, salt);
TextEncryptor
데이터를 문자열로 관리
Encryptors.noOpText()
- 값을 암호화하지 않는 더미 TextEncryptor 반환
Encryptors.text()
- Encryptors.standard 메서드로 암호화 작업 관리
- 암호화 프로세스에 임의의 초기화 벡터가 생성되기 때문에 같은 입력으로 encrypt 메서드를 반복 호출해도 다른 출력이 반환됨
Encryptors.delux()
- 암호화 프로세스에 임의의 초기화 벡터가 생성되기 때문에 같은 입력으로 encrypt 메서드를 반복 호출해도 다른 출력이 반환됨
- Encryptors.stronger 인스턴스 이용
Encryptors.queryableText()
- 순차 암호화 작업에서 입력이 같으면 같은 출력을 생성하도록 보장
String valueToEncrypt = "HELLO";
TextEncryptor e = Encryptors.noOpText();
String encrypted = e.encrypt(valueToEncrypt);
String decrypted = e.decrypt(encrypted);
// 암호기 메서드 종류
TextEncryptor e = Encryptors.noOpText();
TextEncryptor e = Encryptors.text(password, salt);
TextEncryptor e = Encryptors.delux();
TextEncryptor e = Encryptors.queryableTexxt();
'Spring > security' 카테고리의 다른 글
[시큐리티] SecurityContext (0) | 2023.03.16 |
---|---|
[시큐리티] AuthenticationProvider (0) | 2023.03.15 |
[시큐리티] UserDetailsService (0) | 2023.03.13 |
[시큐리티] 구성 요소 재정의 (0) | 2023.03.10 |
[시큐리티] 인증 방법 (0) | 2023.03.10 |