[Spring Security] PasswordEncoders를 이용한 비밀번호 관리

10000JI·2024년 1월 29일
0

Spring Boot

목록 보기
6/15

Spring Security에서 비밀번호가 기본적으로 인증되는 과정

Spring Security의 핵심 개념 중 하나인 PasswordEncoder에 대해 살펴보자.

또한 엔드 유저 인증 과정에서 PasswordEncoder가 어떤 역할을 하는지에 대해서도 알아보자.

기본 로직 이해

Spring Security에서는 보안상의 이유로 기본적으로 비밀번호를 일반 텍스트로 다루지 않는다.

다루진 않지만 일단 일반 텍스트로 비밀번호를 저장하는 기본 로직을 먼저 살펴보자.

엔드 유저는 자신의 usernamepassword를 입력한다.

Spring SecurityAuthenticationProvider 내부의 모든 로직을 실행하고, UserDetailsManager의 구현 클래스 내부에 있는 loadUserByUsername() 메소드 도움으로 저장소에 있는 모든 정보를 불러오라고 할 것이다.

유저 정보를 불러온 다음 Spring Security에선 엔드 유저가 제공한 비밀번호와 데이터베이스에 불러온 비밀번호를 비교한다. (자바의 equals() 메소드)

비밀번호가 일치한다면 로그인에 성공하고 그 반대는 로그인에 실패한다.

문제점과 위협

그러나 이러한 방식은 심각한 보안 문제를 야기할 수 있다.

비밀번호가 일반 텍스트로 저장되어 있기 때문에 데이터베이스에 접근한 DBA나 해커가 이를 쉽게 탈취할 수 있다.

이로 인해 무결성과 기밀성에 심각한 위협이 발생할 수 있다.

PasswordEncoder의 역할

Spring Security에서는 이러한 보안 문제를 해결하기 위해 PasswordEncoder를 도입했다.

PasswordEncoder는 사용자의 비밀번호를 안전하게 저장하고 검증하는 데 사용된다.

실제로 Spring Security에서 비밀번호 검증은 DaoAuthenticationProvider 클래스 내부의 authenticate() 메소드에서 이루어진다.

침고로 PasswordEncoderNoOpPasswordEncoderPasswordEncoder로 갈린다.

NoOpPasswordEncoder: 실제로 비밀번호를 암호화 또는 해시화하지 않고 사용자가 제공한 비밀번호를 그대로 저장한다.
주로 개발 및 테스트 목적으로 사용되며, 실제 프로덕션 환경에서는 권장되지 않는다. 사용자의 비밀번호를 평문으로 저장하기 때문에 보안에 취약하다

PasswordEncoder: Spring Security에서 제공하는 비밀번호 인코딩을 위한 일반적인 인터페이스이다.
이를 구현한 다양한 구현체들이 있으며, 사용자의 비밀번호를 안전하게 암호화 또는 해시화하여 저장한다.
예를 들면 BCryptPasswordEncoder, MessageDigestPasswordEncoder 등이 있다.
프로덕션 환경에서는 보안을 강화하기 위해 적절한 PasswordEncoder를 선택하여 사용하는 것이 권장된다.

문제 해결과 안전한 방식 도입

일반 텍스트로 비밀번호를 저장하는 것은 위험하므로 이를 보완하기 위해 안전한 PasswordEncoder를 도입하는 방법에 대해 알아보자.

Spring Security에서 제공하는 고급 PasswordEncoder들을 활용하여 데이터베이스에 안전하게 비밀번호를 저장하는 방법으로 구현해보자.

PasswordEncoders를 이용한 비밀번호 관리

업계에서 주로 사용되는 비밀번호 관리 옵션들과 그에 따른 고려사항에 대해 다뤄보자.

웹 애플리케이션 초기 시절부터 현재까지의 발전과 함께, 인코딩, 암호화, 해싱과 같은 다양한 옵션들이 등장하였다.

각각의 특징과 적합한 사용처를 알아보자.

인코딩

개념

인코딩은 데이터를 한 형식에서 다른 형식으로 변환하는 과정이다.

그러나 이는 기밀성을 가지지 않으며, 어떤 인코딩 값이든 다시 디코딩이 가능하다.

즉, 일반 텍스트 비밀번호를 인코딩하면 누구나 디코딩하여 원래 비밀번호를 알 수 있다.

따라서 비밀번호 관리에는 적합하지 않다.

사용처

인코딩은 주로 음성 파일이나 영상 파일을 압축할 때 인코딩과 디코딩을 사용한다.

유형

  1. ASCII

  2. BASE64

  3. UNICODE

암호화

개념

암호화는 데이터를 안전하게 변환하여 기밀성을 보장하는 방법이다.

특정 알고리즘과 비밀 키(secret)를 사용하여 일반 텍스트를 암호화한다.

특정 암호화 값의 일반 텍스트 비밀번호가 무엇인지 알고싶다면 복호화를 해야한다.

복호화하기 위해서는 동일한 알고리즘과 키를 필요로 한다.

이 암호화 알고리즘과 비밀 키는 주로 백엔드 애플리케이션 내부에 기밀 데이터로 관리된다. 따라서 인코딩보다 훨씬 낫다

고려사항

서버 관리자나 특정 권한을 가진 사용자가 알고리즘과 비밀 키에 접근할 수 있다는 제한이 있다.

일반 텍스트로 복호화할 가능성이 존재하므로, 엔드 유저 비밀번호 관리에는 적합하지 않는다.

해싱

개념 및 이점

해싱은 일방향 함수를 사용하여 데이터를 고정된 길이의 문자열로 변환하는 것이다.

일반 텍스트 비밀번호에 해싱을 적용하면, 초기 비밀번호를 알아내기 어렵거나 불가능하게 만든다.

비가역적이고, 해시값만 알고 있어도 일반 텍스트 비밀번호를 알 수 없기 때문에 데이터베이스에 안전하게 저장할 수 있다

즉, 해싱은 해시값을 일반 텍스트 비밀번호로 되돌릴 수 없다는 이점이 있다

로그인 작업에서의 해싱

로그인 작업에서는 사용자가 입력한 비밀번호에 해싱을 적용하여 새로운 해시값을 생성한다.

데이터베이스에는 이미 등록된 사용자의 비밀번호에 대한 초기 해시값이 저장돼 있다.

로그인 시에는 두 해시값을 비교하여 성공 또는 실패를 결정한다.

해싱 작동 방법 시연

Bcrypt 알고리즘을 사용한 해싱 작동 방법을 시연한다.

여기서의 Encrypt는 해싱이라고 보면 된다. (=encrypted hash)

< 이점 >

  1. 해시값을 보기만 해서는 초기 텍스트 비밀번호가 무엇인지 누구도 맞출 수 없다.

  2. 해싱의 또 다른 이점은 동일한 일반 텍스트 비밀번호를 한 번 더 해싱하면 초기 해시값과는 다른 문자열 표현을 반환한다.

  3. 하지만 내부적으로 이 문자열은 해시값을 가지기에 이 해시값은 항상 같다.
    이 이점이 없다면 1234와 같이 같은 비밀번호를 가진 사람들은 데이터베이스에 같은 해시 문자열을 저장할 것이고 이것이 데이터베이스 쿼리를 통해 탈취 당할 수 있다.

등록 시에는 비밀번호를 입력하고 해당 값에 대한 해시값을 생성하여 데이터베이스에 저장한다.

로그인 시에는 입력된 비밀번호를 해싱하여 데이터베이스에 저장된 해시값과 비교하여 인증한다.

인코딩, 암호화, 해싱 비교

인코딩과 디코딩은 안전하지 않으며, 암호화 역시 비밀 키가 노출되면 취약하다.

해싱은 비가역적이며, 동일한 입력에 대해 항상 동일한 해시값을 반환한다.

해싱은 데이터베이스에 비밀번호를 안전하게 저장하고 인증하는 데에 사용된다.

해싱과 PasswordEncoders로 비밀번호가 인증되는 과정

앞선 해싱에 대한 강의와 일맥상통하면서 Spring Security에서의 구체적인 활용 방법을 다뤄보자.

유저는 본인의 자격 증명을 입력 (username:Adimn, Password:12345)

Spring Security는 PasswordEncoder들 중 하나를 활용한다.

PasswordEncoder의 도움으로 Spring Security는 엔드 유저가 입력한 비밀번호를 해싱 시도한다.

먼저 입력한 비밀번호의 해시 문자열이 f32c..........adv로 끝난다고 가정하자.

해시가 완료되면 배경에서 Spring Security는 엔드 유저의 등록 절차에서 생성된 기존 해시값을 데이터베이스에서 불러온다.

그리고 이 해시값을 UserDetailsObject에 보유한다.

우리가 데이터베이스에서 불러온 해시 문자열은 g22h.......bef로 끝난다.

두 개의 해시 문자열은 다르지만 해시값은 동일하다.

그리고 해시값이 동일하면 로그인 작업이 성공적일 것이고, 그렇지 않으면 로그인에 실패한다.

이처럼 PasswrodEncoder는 해시 문자열들을 매칭하고, 해시값을 찾는 것,해시값의 일치 여부 등 모든 것을 처리한다.

정리하자면 다음과 같다.

해싱의 재확인

유저가 입력한 자격 증명을 Spring Security의 PasswordEncoder를 활용하여 해싱 시도한다.

생성된 해시 비밀번호는 데이터베이스에 저장된 초기 해시값과는 다르다.

Spring Security는 등록 절차에서 생성된 기존 해시값을 데이터베이스에서 가져와 UserDetailsObject에 저장한다.

PasswordEncoder의 역할

PasswordEncoder는 두 개의 해시값을 매칭하고 해시값을 찾는 등의 작업을 처리한다.

두 해시값이 동일하면 로그인 작업이 성공하고, 그렇지 않으면 실패한다.

모든 작업에서 일반 텍스트 비밀번호를 데이터베이스에 저장하지 않고, 해시 문자열 형태로 처리한다.

PasswordEncoder의 중요성

PasswordEncoder를 통해 해싱 표준을 구현함으로써 안전하고 비가역적인 비밀번호 관리가 가능하다.

데이터베이스에서 일반 텍스트 비밀번호를 사용하지 않으며, 해시값끼리의 안전한 비교가 이루어진다.

결론

Spring Security와 PasswordEncoder를 활용하면 안전하고 효과적인 비밀번호 관리가 가능하다.

모든 비밀번호는 해시값으로 안전하게 저장되며, 로그인 시에 안전한 비교가 이루어진다.

PasswordEncoder 인터페이스 심층 분석

Spring Security 프레임워크 내부의 PasswordEncoder 인터페이스와 그 구현 클래스들에 대해 자세히 살펴보자.

PasswordEncoder는 인터페이스로서, 여러 메소드를 제공하여 사용자의 비밀번호를 해싱하고 검증하는 역할을 한다.

PasswordEncoder 인터페이스

PasswordEncoder 인터페이스는 두 개의 추상 메소드한 개의 기본 메소드로 구성되어 있다.

  • encode(rawPassword): 엔드 유저의 등록 절차에서 활용.
    일반 텍스트 비밀번호를 받아 해당 PasswordEncoder에 기반한 해시 문자열로 변환한다.

  • matches(rawPassword, encodedPassword): 첫 번째 매개변수인 유저가 입력한 비밀번호 rawPassword와 두 번째 매개변수인 loadUserByUsername의 도움으로 데이터베이스에서 불러온 해시 비밀번호 encodedPassword 를 비교한다.

    해시값이 동일하면 matches 메소드는 true로 반환하고 로그인 작업은 성공적이다.

    반대로 해시값이 일치하지 않으면 false를 반환하고 로그인 작업은 실패한다.

  • upgradeEncoding(): 기본적으로는 false를 반환한다.

    이 메서드의 목적은 타인이 해킹하고 복호화하여 해시값이 일반 텍스트 비밀번호를 알아내는 것을 어렵게 만들고 싶다면 비밀번호를 두 번 인코딩할 수 있다.

    즉, 해싱을 한 번만 하는게 아니라 두 번 하는 것이다.

    간단히 말해 true를 반환한다면 비밀번호를 추가로 인코딩할 수 있도록 한다.

PasswordEncoder 인터페이스 구현체

PasswordEncoder 인터페이스를 구현한 클래스들은 다양한 해싱 알고리즘과 보안 수준을 제공한다.

NoOpPasswordEncoder와 같은 클래스를 살펴보면, 인코딩과 매칭을 수행하는 메소드들을 구현한다.

PasswordEncoder 구현 클래스 심층 분석 - Part1

Spring Security 프레임워크에서 제공하는 다양한 PasswordEncoder 구현 클래스를 살펴보자.

이 중에서도 가장 중요한 6가지 PasswordEncoder에 대해 강조하고, 각 클래스의 특징과 사용 시 주의할 점을 살펴보자.

NoOpPasswordEncoder

가장 간단한 형태의 PasswordEncoder로, 해싱이나 암호화를 수행하지 않고 일반 텍스트로 비밀번호를 다룬다.

데모 애플리케이션이나 우선순위가 낮은 비운영 환경에만 사용하며, 실제 운영 환경에서는 피해야 한다.

StandardPasswordEncoder

레거시 애플리케이션을 지원하기 위해 만들어진 PasswordEncoder로, 무작위 솔트값과 SHA-256 해싱 알고리즘을 사용한다.

운영 환경에는 추천하지 않는다.

안전하지 않으며, Spring Security 팀에서 레거시 목적으로만 제공된다고 명시하고 있다.

또한 Spring Security에서는 최신버전으로 Boot 환경에서 개발하고 있다면 BcryptPasswordEncoder를 고려해볼 것을 강조하고 있다.
이는 보안 측면이나 다른 언어와의 상호 운영성 측면에서 더 나은 선택이라고 말하고 있다.

Pbkdf2PasswordEncoder

5~6년 전까지 안전하게 여겨졌던 PasswordEncoder이지만, 최근에는 고성능 GPU 기계의 등장으로 손쉽게 해시값에 무차별 대입 공격을 가하고 일반 텍스트 비밀번호를 추측할 수 있어 안전하지 않아졌다.

현재의 하드웨어 성능으로는 추천되지 않으며, 최신 웹 애플리케이션에는 사용하지 않는 것이 좋다.

이처럼 그림에 있는 왼쪽 PasswordEncoder들은 운영 웹 애플리케이션에 고려해선 안 된다.

BcryptPasswordEncoder, SCryptPasswordEncoder, Argon2PasswordEncoder

그림에 있는 우측 PasswordEncoder들은 운영 웹 애플리케이션에 고려할 수 있다.

강력한 해싱 알고리즘을 사용하여 보안을 강화한 PasswordEncoder이다.

현대적이고 안전한 웹 애플리케이션에 적합하며, 무차별 대입 공격에 대비하여 강력한 보안을 제공한다.

무차별 대입 공격

해커가 다수의 비밀번호를 추측하는 방식 중 하나로, 일반적인 비밀번호나 사전 단어를 대입해가며 공격하는 방식이다.

이를 예방하기 위해 개발자가 할 수 있는 일은 해싱 로직을 지연시켜 해커가 접근하지 못하게 할 수 있다.

  1. 엔드 유저들이 5개, 6개 철자로 된 단순한 비밀번호를 선택하지 않도록 초기에 경고하는 것이다.
    숫자만 입력하지 않도록, 영문만 입력하지 않도록 또는 8개 철자보다 짧은 비밀번호를 받지 않도록 등 이라는 로직을 작성할 수 있다.

  2. 강력한 해싱 알고리즘을 사용한다.
    Bcrypt 알고리즘이나 Scrypt 알고리즘 또는 해커의 CPU 또는 메모리 성능을 많이 잡아먹는 어떤 해싱 알고리즘이면 된다.

PasswordEncoder 구현 클래스 심층 분석 - Part2

운영 웹 애플리케이션에 적합한 세 가지 강력한 PasswordEncoder에 대해 살펴보자.

BCryptPasswordEncoder, SCryptPasswordEncoder, 그리고 Argon2PasswordEncoder는 각각의 장점을 가지고 있어 선택이 중요하다.

PasswordEncoder가 제공하는 이점을 살펴보고, 어떤 상황에서 어떤 것을 선택해야 하는지 알아보자.

BCryptPasswordEncoder

특징

BCrypt 해싱 알고리즘 사용.

장점

  1. 레거시 알고리즘에 비해 안전하며, 지속적인 업데이트로 보안 강화.

  2. BCryptPasswordEncoder에 설정한 작업량 또는 라운드 수에 따라 이 해싱 알고리즘이 사용하는 CPU 연산은 더 많아진다.

    따라서 해커가 무차별 대입 공격을 위해 많은 연산 능력을 필요로 한다.

  3. 안전하면서도 성능에 민감한 웹 애플리케이션에 적합

SCryptPasswordEncoder

특징

BCrypt의 고급 버전으로, 연산능력 뿐 아니라 메모리 요구도 추가됨.

장점

1.BCrypt에 비해 더욱 안전한 알고리즘이다.

  1. 해커는 연산능력 뿐만 아니라 메모리도 제공해야 하므로 무차별 대입 공격을 어렵게 만듦.

  2. 보다 강화된 보안이 필요한 웹 애플리케이션이다.

Argon2PasswordEncoder

특징

최신이면서도 강력한 해싱 알고리즘으로, (1) 연산, (2) 메모리, (3) 다중 스레드 요구.

장점

  1. 세 가지 자원을 모두 필요로 하기에 무차별 대입 공격이 사실상 불가능.

  2. 가장 최신 알고리즘

  3. 최대 수준의 보안이 필요한 웹 애플리케이션.

선택 가이드라인

  1. 연산 능력과 메모리: 보안 수준을 선택할 때, 연산과 메모리 요구를 고려해야 한다.

    무차별 대입 공격에 대비하기 위해선 BCrypt, SCrypt, Argon2 중 선택한다.

  2. 성능 고려: SCrypt, Argon2 는 코드와 서버로부터 많은 자원을 요구하기 때문에 애플리케이션의 성능에 민감한 경우 BCrypt 고려한다.

    무차별 대입 공격에 대한 안전성은 여전하다.

결론

BCryptPasswordEncoder, SCryptPasswordEncoder, 그리고 Argon2PasswordEncoder 중에서 선택할 때는 보안 수준과 성능을 고려해야 한다.

보통 BCryptPasswordEncoder가 안전하면서도 성능에 민감한 웹 애플리케이션에 적합하며, 최대 수준의 보안이 필요한 경우 Argon2PasswordEncoder를 고려할 수 있다.

각 알고리즘의 특징을 잘 이해하고 적절한 선택을 통해 웹 애플리케이션의 보안성을 향상시킬 수 있다.

Bcrypt PassworkEncoder를 사용한 새로운 유저 등록 실습

Bcrypt PasswordEncoder를 사용하여 우리의 Spring Boot 웹 애플리케이션에 보안을 강화해보자.

기존의 springsecsection3 프로젝트를 복사하여 springsecsection4로 이름을 변경하고, pom.xml 파일에서도 해당 이름으로 수정합니다.

<artifactId>springsecsection4</artifactId>
<name>springsecsection4</name>

ProjectSecurityConfig 클래스 수정

ProjectSecurityConfig 클래스 내의 주석 코드 및 NoOpPasswordEncoder 관련 코드를 모두 삭제한다.

대신에 BcryptPasswordEncoder를 사용하기 위해 해당 클래스에서 빈을 생성합니다.

package com.eazybytes.springsecsection2.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

import javax.sql.DataSource;

@Configuration
public class ProjectSecurityConfig {

    //람다(Lambda) DSL 스타일 사용을 권장
    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        /**
         * 사용자 정의 보안 설정
         */
        http.csrf((csrf) -> csrf.disable())
                .authorizeHttpRequests((requests)->requests
                        .requestMatchers("/myAccount","/myBalance","/myLoans","/myCards").authenticated()
                        .requestMatchers("/notices","/contact","/register").permitAll())
                .formLogin(Customizer.withDefaults())
                .httpBasic(Customizer.withDefaults());
        return http.build();
    }


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

LoginController에서 PasswordEncoder 활용

이제 비밀번호를 등록하는 부분에서 NoOpPasswordEncoder 대신에 BCryptPasswordEncoder를 사용하도록 수정한다.

PasswordEncoder 활용해야 할 첫 지점은 등록 절차 도중이다.
왜냐하면 유저가 등록 절차에서 본인의 비밀번호를 입력할 때가 일반 텍스트 비밀번호를 해싱하고 데이터베이스에 저장해야 하는 첫 지점이기 때문이다.

LoginController 클래스에서 registerUser() 매서드의 매개변수로 받은 Customer의 Pwd를 가져와 PasswordEncoder 진행 후 setter 매개변수에 주입한다.

package com.eazybytes.springsecsection2.controller;

import com.eazybytes.springsecsection2.model.Customer;
import com.eazybytes.springsecsection2.repository.CustomerRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class LoginController {

    private final CustomerRepository customerRepository;

    private final PasswordEncoder passwordEncoder;

    @PostMapping("/register")
    public ResponseEntity<String> registerUser(@RequestBody Customer customer) {
        Customer savedCustomer = null;
        ResponseEntity response = null;
        try {
            String hashPwd = passwordEncoder.encode(customer.getPwd());
            customer.setPwd(hashPwd);
            //고객 정보 저장
            savedCustomer = customerRepository.save(customer);

            //CrudRepository에선 고객 정보 저장 후, 고객 정보를 그대로 리턴
            //리턴 받은 고객정보의 기본키(=id)가 0보다 크다면 정상저장된 것
            if (savedCustomer.getId() > 0) {
                //상태코드 201번
                response = ResponseEntity
                        .status(HttpStatus.CREATED)
                        .body("Given user details are successfully registered");
            }
        } catch (Exception ex) {
            //상태코드 500번
            response = ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("An exception occured due to " + ex.getMessage());
        }
        return response;
    }
}

테스트 및 확인

프로젝트를 빌드하고 웹 애플리케이션을 시작한 후, 새로운 유저를 등록하여 Bcrypt 해싱 알고리즘이 제대로 작동하는지 확인한다.

데이터베이스에서 해당 유저의 비밀번호가 해시값으로 저장되는 것을 확인할 수 있다.

BcryptPasswordEncoder를 사용한 로그인 실습

이전에도 언급했듯이, 비밀번호를 안전하게 저장하고 비교하는 데에 BCryptPasswordEncoder를 사용하는 이유는 여러 가지가 있다.

이에 대한 자세한 설명을 살펴보도록 하자.

BCryptPasswordEncoder의 특징

  1. 해시 텍스트 패턴: $2가 가장 먼저 나와야 한다. 그 다음으로는 'a', 'y', 'b' 중 하나를 가질 수 있다.

  2. BCrypt 버전: BCryptVersion 열거를 통해 확인해보면 $2a, $2y, $2b 등 여러 버전이 있다.

    주로 Spring Security는 기본적으로 $2a 버전을 사용한다. 필요에 따라 설정을 변경할 수 있다.

  3. BCrypt 버전 변경: ProjectSecurityConfig에서 BCryptPasswordEncoder의 빈 생성자를 호출하는데, 이는 버전, 작업량 변수, 라운드 수 등을 고려하지 않는 기본 생성자를 사용하는 것이다.

    따라서 원한다면 버전을 변경할 수 있으며, 이는 this(strength, null)을 통해 해당 생성자로 이동하게 된다.

  4. 작업량 변수 및 라운드 수: 기본 생성자에서 -1 값을 사용하면, 내부적으로 this(strength, null)을 호출하는데, 여기서는 다시 this(strength, null)이 기본 버전을 $2a로 설정하는 생성자를 호출한다. strength 값이 -1이면 기본 설정으로 10을 사용하며, 이는 해싱 과정에서 필요한 라운드 수 또는 작업량 변수이다.

    strength 값의 범위는 4에서 31까지이다.

  5. SecureRandom 값: SecureRandom 값의 목적은 무작위로 생성된 솔트 값을 추가하여 해싱 알고리즘을 더 안전하게 만드는 것이다.

    이 값은 사용자의 비밀번호와 함께 해싱되어 무작위성을 높인다.

로그인 시 실제 비밀번호 비교

굳이 사용자 정의 PasswordEncoder 만들지 말자

Spring Security에서는 다양한 PasswordEncoder를 제공하지만, 필요에 따라 사용자가 직접 구현할 수도 있다.

하지만 이미 제공되는 PasswordEncoder가 업계 표준을 준수하고 있으며, 새로운 비밀번호 알고리즘을 개발할 때 놓치기 쉬운 많은 유스케이스가 있으므로 추천하지 않는다.

모든 PasswordEncoder 및 관련 클래스는 org.springframework.security.crypto 패키지에서 찾을 수 있다.

profile
Velog에 기록 중

0개의 댓글