[Spring Security] PasswordEncoder

2024. 6. 27. 20:36·Backend/Spring Security

일반적인 Spring Security 내부 흐름입니다. 우리는 InMemoryUserDetailsManager를 사용하는 대신에 직접 loadByUsername()을 오버라이딩하여 사용해보도록 하겠습니다. 

 

 

실습 - User 정보를 SQL 스크립트를 활용하여 수동 입력

Config - SecurityConfig

@Configuration
public class ProjectSecurityConfig {
    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((requests) ->
                requests.requestMatchers("/myAccount", "/myBalance", "/myLoans", "/myCards").authenticated()
                        .requestMatchers("/notices", "/contact").permitAll()
        );
        http.formLogin(Customizer.withDefaults());
        http.httpBasic(Customizer.withDefaults());

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() { 
        return NoOpPasswordEncoder.getInstance();
    }
}

 

Repository - CustomerRepository

public interface CustomerRepository extends JpaRepository<Customer, Long> {
    List<Customer> findByEmail(String email);
}

 

Model - Customer

@Entity
@Getter
public class Customer {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String email;
    private String pwd;
    private String role;
}

 

Service - BankUserDetails

BankUserDetails는 UserDetailsService의 실질적인 구현체가 되고, 다른 UserDetailsManager의 영향을 받지 않게 됩니다. 

@RequiredArgsConstructor
@Service
public class BankUserDetails implements UserDetailsService {
    private final CustomerRepository customerRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String userName, password = null;
        List<GrantedAuthority> authorities = null;
        List<Customer> customers = customerRepository.findByEmail(username);
        if(customers.isEmpty()) {
            throw new UsernameNotFoundException("User details not found for the user : " + username);
        } else {
            userName = customers.get(0).getEmail();
            password = customers.get(0).getPwd();
            authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority(customers.get(0).getRole()));
        }
        return new User(userName, password, authorities);
    }
}

 

 

새로운 유저 등록을 허용하는 새 REST API 구축

SecurityConfig에서 permitAll()을 해주고, 다시 POST 요청을 보내도 에러가 발생합니다. 그 이유는 Spring Security 에서 제공하는 CSRF 보안 때문입니다. 기본 설정은 어떤 POST 요청이든 간에 DB나 백엔드 내부의 데이터를 수정하고자 하는 것이면 막도록 되어 있습니다. 일단 테스트를 위해 CSRF를 해제하겠습니다.

http.csrf(AbstractHttpConfigurer::disable)

 

 

그 결과, 정상적으로 유저 정보를 받아올 수 있었습니다. 

 

 

 

 

실습 - Bcrypt PasswordEncoder를 사용한 새로운 유저 등록 (보안 강화)

passwordEncoder에서 기존에 넘겨주던 NoOpPasswordEncoder가 아닌 BCryptPasswordEncoder를 념겨주도록 코드를 수정해줍니다. 

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

 

Postman을 통해 유저 자격 증명을 POST로 전송합니다. 

결과 !! 

NoOpPasswordEncoder를 이용한 방법은 문자열 그대로 저장되기 때문에 보안에 취약합니다. 하지만 BCryptPasswordEncoder의 경우 해싱 알고리즘을 이용한 방법으로 저장되기 때문에 상대적으로 안전한 모습을 볼 수 있습니다. 

 

 

 

'Backend/Spring Security' 카테고리의 다른 글
  • CSRF 공격 시나리오 및 방어 방법
  • [Spring Security] 유저 정의와 관리
  • [Spring Security] OAuth 2.0 개념과 이해
  • [Spring Security] 내부 흐름 - 2
kimdozzi
kimdozzi
끝까지 포기하지 않으면, 내가 다 이겨!
  • kimdozzi
    도브로
    kimdozzi
  • 전체
    오늘
    어제
    • 분류 전체보기 (132)
      • Problem Solving (49)
        • Baekjoon (29)
        • Programmers (0)
        • LeetCode (17)
        • 삼성 유형 (2)
      • Computer Science (27)
        • Operating System (2)
        • Algorithms (13)
        • Network (6)
        • DataBase (6)
      • Backend (33)
        • JavaScript (0)
        • TypeScript (6)
        • Java (7)
        • Spring Boot (7)
        • Spring Security (6)
        • JPA (2)
        • Mybatis (1)
        • Junit5 (1)
        • Redis (3)
      • DevOps (14)
        • Git, Github (5)
        • docker (4)
        • AWS (3)
        • nginx (2)
      • etc (6)
        • IntelliJ (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 티스토리
    • 설정
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    알고리즘
    오프라인 쿼리
    구간합
    인터페이스
    티스토리챌린지
    컨테이너
    segment tree
    인덱스 시그니처
    PrefixSum
    인덱서블 타입
    도커
    구간 업데이트
    세그먼트 트리
    AWS
    점 업데이트
    CORS
    백준
    파이썬
    docker
    누적합
    python
    타입스크립트
    interface
    docker image
    Bucket
    S3
    imos법
    온라인 쿼리
    TypeScript
    삼성기출
    오블완
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
kimdozzi
[Spring Security] PasswordEncoder
상단으로

티스토리툴바