Spring Framework
[Spring Security] PasswordEncoder
터프남
2023. 3. 1. 14:41
728x90
반응형
PasswordEncoder 인터페이스
비밀번호를 안전하게 암호화 하도록 제공해주는 인터페이스이다. 스프링 시큐리티가 이미 구현해 놓은 여러 암호화 구현체들이 있다.
public interface PasswordEncoder {
/**
* Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
* greater hash combined with an 8-byte or greater randomly generated salt.
*/
String encode(CharSequence rawPassword);
/**
* Verify the encoded password obtained from storage matches the submitted raw
* password after it too is encoded. Returns true if the passwords match, false if
* they do not. The stored password itself is never decoded.
* @param rawPassword the raw password to encode and match
* @param encodedPassword the encoded password from storage to compare with
* @return true if the raw password, after encoding, matches the encoded password from
* storage
*/
boolean matches(CharSequence rawPassword, String encodedPassword);
/**
* Returns true if the encoded password should be encoded again for better security,
* else false. The default implementation always returns false.
* @param encodedPassword the encoded password to check
* @return true if the encoded password should be encoded again for better security,
* else false.
*/
default boolean upgradeEncoding(String encodedPassword) {
return false;
}
}
- Spring Security 5.0 이전에는 기본 PasswordEncoder가 평문을 지원하는 NoOpPasswordEncoder가 있었으나 현재는 Deprecated 되었다. 보안상 평문을 지원하지 않는 것이 맞는 것 같다.
- 아래는 스프링시큐리티에 구현되어있는 PasswordEncoder의 구현체 클래스목록이다. NoOpPasswordEncoder가 실선처리되어있는 것 확인!
- 암호화 하는데 자주 보이는 Bcrypt, Pbkdf2 등이 보인다.
암호화 포맷
DelegatingPasswordEncoder.java 클래스에 있는 설명으로 첨부
- {암호화 알고리즘}password 이다.
- bcrypt, noop, pbkdf2, scrypt, sha256 포맷이 있고 기본 포맷은 Bcrypt이다.
생성하는 방법
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
여러개의 PasswordEncoder 유형을 선언한 뒤, 상황에 맞게 선택해서 사용할 수 있도록 지원하는 Encoder 이다.
이 말이 무엇이냐 하면 PasswordEncoder는 인터페이스이므로 내가 직접 암호화 알고리즘을 구현해서 추가해줄 수 있다.
public final class PasswordEncoderFactories {
private PasswordEncoderFactories() {
}
/**
* Creates a {@link DelegatingPasswordEncoder} with default mappings. Additional
* mappings may be added and the encoding will be updated to conform with best
* practices. However, due to the nature of {@link DelegatingPasswordEncoder} the
* updates should not impact users. The mappings current are:
*
* <ul>
* <li>bcrypt - {@link BCryptPasswordEncoder} (Also used for encoding)</li>
* <li>ldap -
* {@link org.springframework.security.crypto.password.LdapShaPasswordEncoder}</li>
* <li>MD4 -
* {@link org.springframework.security.crypto.password.Md4PasswordEncoder}</li>
* <li>MD5 - {@code new MessageDigestPasswordEncoder("MD5")}</li>
* <li>noop -
* {@link org.springframework.security.crypto.password.NoOpPasswordEncoder}</li>
* <li>pbkdf2 - {@link Pbkdf2PasswordEncoder}</li>
* <li>scrypt - {@link SCryptPasswordEncoder}</li>
* <li>SHA-1 - {@code new MessageDigestPasswordEncoder("SHA-1")}</li>
* <li>SHA-256 - {@code new MessageDigestPasswordEncoder("SHA-256")}</li>
* <li>sha256 -
* {@link org.springframework.security.crypto.password.StandardPasswordEncoder}</li>
* <li>argon2 - {@link Argon2PasswordEncoder}</li>
* </ul>
* @return the {@link PasswordEncoder} to use
*/
@SuppressWarnings("deprecation")
public static PasswordEncoder createDelegatingPasswordEncoder() {
String encodingId = "bcrypt";
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put(encodingId, new BCryptPasswordEncoder());
encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
encoders.put("SHA-256",
new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
encoders.put("argon2", new Argon2PasswordEncoder());
return new DelegatingPasswordEncoder(encodingId, encoders);
}
}
createDelegatingPasswordEncoder를 보면 new DelegatingPasswordEncoder 를 실행하는데 내가 직접 구현한 암호화 알고리즘을 위임해주는 역할을 한다.
직접 구현한 암호화 알고리즘이 있으면 이런식으로 Bean을 생성하면 된다. 위의 createDelegatingPasswordEncoder 메소드를 보면 기본은 Bcrypt이다.
@Bean
public PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put("직접구현한 알고리즘", new 내가만든알고리즘());
return new DelegatingPasswordEncoder("직접구현한 알고리즘", encoders);
}
참고
스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security - 인프런 | 강의
초급에서 중.고급에 이르기까지 스프링 시큐리티의 기본 개념부터 API 사용법과 내부 아키텍처를 학습하게 되고 이를 바탕으로 실전 프로젝트를 완성해 나감으로써 스프링 시큐리티의 인증과
www.inflearn.com
728x90
반응형