오봉이와 함께하는 개발 블로그

Spring - SpringSecurity 사용해서 패스워드 암호화 하기 본문

BE/Spring

Spring - SpringSecurity 사용해서 패스워드 암호화 하기

오봉봉이 2022. 7. 19. 23:47
728x90

개요

서버에서 패스워드를 암호화하여 DB에 넣는 작업을 하고 싶었다.
블로그에 기록하진 않았지만, 전에 한 번 사용해 봤으나 기억이 나지 않아 블로그에 기록해 보려 한다.

BCryptPasswordEncoder

BCryptPasswordEncoder란 Spring Security에서 제공하는 클래스 중 하나로, 암호화하는 데 사용할 수 있는 메소드를 가진 클래스다.

Spring Security(이하 스프링 시큐리티)는 자바 서버 개발을 위해 필요로 하는 인증, 권한 부여 및 보안 기능을 제공하는 프레임워크다.

BCryptPasswordEncoder는 사용자가 제출한 문자열을 인코딩 해주고, DB에 저장된 값과 비교할 수 있게 기능을 제공하고 있다.

기본적으로 웹 사이트를 개발할 때 값은 DB에 저장한다.
이때 DB에도 기본적으로 보안 장치가 되어 있겠지만, 혹여나 뚫리게 된다면 내부 데이터가 무방비하게 노출되기 때문에 보안이 필요한 정보는 암호화하여 저장하는 것이 좋을 것이다.

총 3가지(encode(), matches(), upgradeEncoding()) 메소드를 제공하는데, 이 중 2개(encode(), matches())의 메소드를 사용했다.

encode(java.lang.CharSequence rawPassword)

  • 패스워드를 암호화하는 메소드다.
  • 해당 메소드는 해시 단방향 암호화를 제공하고, 랜덤하게 생성된 솔트(salt)를 지원한다.
  • 매개변수는 String타입이며 반환타입도 String이다.
  • 똑같은 문자열을 인코딩하더라도 매번 다른 인코딩 문자열을 반환한다.

matches(java.lang.CharSequence rawPassword, java.lang.String encodePassword)

  • 사용자가 제출한 raw문자열을 인코딩된 문자열과 비교해서 일치 여부를 확인한다.
  • 첫 번째 매개변수는 raw문자열, 두 번째 문자열은 인코딩된 문자열이다.
  • 반환 타입은 boolean이다.

upgradeEncoding(java.lang.String encodePassword)

  • 더 나은 보안을 위해 제공하는 기능이다.
  • 매개변수는 인코딩된 문자열이다.
  • 인코딩된 문자열을 한 번 더 암호화 한다.
  • 반환 타입은 인코딩이 필요한 경우 true, 필요하지 않은 경우 false를 입력한다.
    • 기본 값은 false

사용 방법

스프링 시큐리티 라이브러리를 추가해야 한다.
Gradle 프로젝트로 진행하였기 때문에 build.gradle에 라이브러리를 추가해 주었다.

implementation 'org.springframework.boot:spring-boot-starter-security'
spring-boot-starter-security는 스프링에서 제공하는 Spring Security를 사용할 수 있도록 하게 해준다.

WebConfigSecurity.java

확실하게 명시하고 사용하는 것이 편하고, 테스트를 편하게 하기 위해 클래스를 하나 만들었다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

}

테스트 코드

간단한 테스트를 위해 테스트 코드를 작성했다.
테스트는 jUnit5를 통해 진행한다.

테스트 클래스에 암호화를 구현한 클래스를 객체로 등록한다.

public class WebSecurityConfigTest {

    WebSecurityConfig webSecurityConfig = new WebSecurityConfig();

/*
..............
*/

}

먼저 암호화가 잘 되는지에 대한 테스트다.
encode()의 매개변수로 rawPW를 넣어주고 encodePW로 문자열을 반환 받는다.
assertThat(rawPW).isNotEqualTo(encodePW)을 통해 rawPW와 encodePW가 같지 않은지를 확인한다.

@Test
    @DisplayName("패스워드 암호화 테스트")
    void encodeTest() {
        // given
        String rawPW = "1234";

        // when
        String encodePW = webSecurityConfig.getPasswordEncoder().encode(rawPW);

        // then
        assertThat(rawPW).isNotEqualTo(encodePW);
    }

두 번째 matches() 메소드에 대한 테스트다.
첫 번째 테스트와 마찬가지로 암호화를 하고, check(Boolean 변수)를 통해 matches()를 통해 반환된 값을 담아준다.
rawPW와 inputPW가 같기 때문에 우리가 원하는 값은 true여야 한다.
assertThat(check).isEqualTo(true)을 통해 check가 true인지 확인한다.

@Test
    @DisplayName("패스워드 일치 테스트")
    void matchTest() {
        // given
        String rawPW = "1234";
        String encodePW = webSecurityConfig.getPasswordEncoder().encode(rawPW);
        String inputPW = "1234";

        // when
        Boolean check = webSecurityConfig.getPasswordEncoder().matches(inputPW, encodePW);

        // then
        assertThat(check).isEqualTo(true);
    }

세 번째 테스트는 패스워드가 불일치할 때의 테스트다
원본값과 입력값이 다르기 때문에 matches()를 사용했을 때 false가 나와주어야 한다.

@Test
    @DisplayName("패스워드 불일치 테스트")
    void notMatchTest() {
        // given
        String originalPW = "1234"; // 설정한 PW의 원본
        String inputPW = "123456"; // 입력한 PW의 원본
        String encodePW = webSecurityConfig.getPasswordEncoder().encode(originalPW); // 설정한 PW를 인코딩한 값

        // when
        Boolean check = webSecurityConfig.getPasswordEncoder().matches(inputPW, encodePW); 
        // 입력한 PW와 설정한 PW를 인코딩한 값을 matches()를 통해 비교한다.
        // originalPW와 inputPW가 다르기 때문에 false 나와야 함.

        // then
        assertThat(check).isEqualTo(false);
    }
728x90
Comments