1. PasswordEncoder
- 비밀번호 암호화를 담당하는 객체
one-way hashing
- 한 번 해싱하면 원래 입력값으로 되돌릴 수 없음 (복호화 불가)
항목 | 설명 |
목적 |
비밀번호를 안전하게 저장하기 위함
|
인증 방식 |
입력된 비밀번호를 해싱하여, DB에 저장된 해시값과 비교
|
장점 |
원문 비밀번호를 저장하지 않으므로 데이터 유출 시 위험 최소화
|
2. Password Storage History
구분 | 설명 | 문제점 / 대응 |
초기 보안 처리 | 비밀번호를 평문으로 저장 DB 접근 제어 기능에 의존 |
계정 정보 탈취 위험
- SQL Injection: 입력값 공격 |
단방향 해싱 도입 | 단방향 해시 함수 사용 (해시값은 복호화 불가능) → 입력 비밀번호를 해시하여 저장된 값과 비교 |
사전 공격 가능성 존재
- 레인보우 테이블: 다양한 해시값을 미리 계산해둔 테이블 |
Salt 도입 | Salt를 해싱에 함께 사용 → 각 해시값을 고유하게 만듦 |
Salt 추가로 레인보우 테이블 무력화
|
Adaptive One-Way Functions 도입 | 하드웨어 성능 발전으로 인해 salt별 레인보우 테이블 생성 가능 → work-factor 조정 (해시 생성 과정에서 필요한 작업량) |
계산 비용 증가로 보안성 확보
단, 성능 저하 trade-off 고려 필요 |
단기 자격 증명으로 전환 | 세션 ID / 토큰 발급 (제한 시간 내에만 유효) → 노출 가능성을 낮추고 보안 매커니즘 성능을 아낌 |
매 요청마다 패스워드 검증 필요 없음
→ 성능 향상 + 보안 강화 |
3. DelegatingPasswordEncoder
구분 | 내용 |
기존 문제점 |
- Spring Security 5.0 이전 기본값은 NoOpPasswordEncoder
- 비밀번호를 평문으로 저장하여 보안에 매우 취약 |
현실적 제약 |
- 이미 NoOpPasswordEncoder를 사용하는 레거시 시스템이 많음
- 해시 기반 마이그레이션은 비용과 복잡성 존재 |
보안 정책의 변화 |
- 비밀번호 저장 방식은 시대에 따라 계속 진화
- Spring Security는 자주 기본값을 변경하기 어려움 |
→ DelegatingPasswordEncoder 도입 |
- 현재 권장되는 방식으로 비밀번호 저장
- 이전 포맷과 호환되어 검증 가능 - 미래 인코딩 방식으로의 유연한 전환 가능 |
Password Storage Format
{id}encodedPassword
- id : 원본 패스워드를 해싱한 PasswordEncoder
- encodedPassword : PasswordEncoder가 해싱한 값
예제
더보기
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
{noop}password
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
Password Encoding
- password storage format의 {id} 값은 DelegatingPasswordEncoder 생성자의 idForEncode 값으로 전달됨
- idForEncode 값을 통해 PasswordEncoder의 구현체가 결정됩니다.
- PasswordEncoder의 구현체는 passwordEncoderForEncode 필드로 담겨지며 encoding 작업을 위임받게 됩니다.
Password Matching
DelegatingPasswordEncoder.match(): 입력된 패스워드와 해싱 패스워드의 일치를 검사
- DelegatingPasswordEncoder가 해싱 패스워드의 {id} 값에 알맞는 위임할 PasswordEncoder 구현체를 찾습니다.
- 위임할 PasswordEncoder가 없거나, 매핑되어 있지 않다면 IllegalArgumentException를 던집니다.
- 위임할 PasswordEncoder가 일치여부를 검사하여 인증을 시도합니다.
3. BCryptPasswordEncoder
bcrypt 알고리즘
- 패스워드 해싱에 보편적으로 사용되는 알고리즘입니다.
- 패스워드 보안의 저항성을 늘리기 위해 의도적으로 많은 연산을 수행합니다.
- 기본적으로 강도 10으로 셋팅되어 있음
- bcrypt 알고리즘의 연산 강도를 trade-off를 고려하여 1정도로 맞추는 것이 일반적입니다.
4. Change Password Configuration
- 패스워드 재설정을 위한 Well-Known URL 제공 → 클라이언트는 패스워드 재설정 URL을 쉽게 알 수 있음
- 기본값: /.well-known/change-password
설정
- 패스워드 재설정 페이지로 리다이렉트 되도록 설정을 제공
더보기
http
.passwordManagement((management) -> management
.changePasswordPage("/update-password")
)
참고
'Spring > Spring Security' 카테고리의 다른 글
[JWT] 1. JWT Token (1) | 2023.10.03 |
---|---|
[Spring Security] 3-4. Authentication: logout (0) | 2023.10.03 |
[Spring Security] 3-2. Authentication: Username/Password (2) | 2023.10.02 |
[Spring Security] 5. 예외 처리 (0) | 2023.09.30 |
[Spring Security] 3-1. Authentication: Architecture (0) | 2021.07.28 |