Gidhub BE Developer

Spring Security 환경에서 Password를 암호화(Encrypt)해보자.

2021-09-06
goodGid

Goal

PasswordEncoder

package org.springframework.security.crypto.password;

public interface PasswordEncoder {
  String encode(CharSequence rawPassword);
  boolean matches(CharSequence rawPassword, String encodedPassword);
  default boolean upgradeEncoding(String encodedPassword) {
    return false;
  }
}
  • SpringSecurity에서 제공하는 PasswordEncoder를 사용하여 Password를 암호화(Encrypt)해보자.

Code

build.gradle

implementation 'org.projectlombok:lombok:1.18.20'
implementation 'org.springframework.boot:spring-boot-starter-security' // [1]
implementation 'org.springframework.boot:spring-boot-starter-web'      // [1]
testImplementation 'org.springframework.boot:spring-boot-starter-test' // [2]
testImplementation 'org.springframework.security:spring-security-test' // [2]
  • [1] : SpringBoot + SpringSecurity 환경을 위한 Dependency를 추가한다.

  • [2] : SpringBoot + SpringSecurity 환경에서 TestCode 작성을 위해 Dependency를 추가한다.

Config

@Configuration
@EnableWebSecurity // [1]
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder(); // [2]
    }
}
  • [1] : SpringSecurity를 기능을 사용하기 위해 어노테이션을 선언해준다.

  • [2] : PasswordEncoder는 Interface이므로 구현체로 BCryptPasswordEncoder를 사용한다.

    구현체에 대한 개념은 [SpringSecurity] PasswordEncoder 글을 참고하자.

Controller

@RestController
@RequestMapping("/security")
public class SecurityController {

    @Autowired
    private PasswordEncoder passwordEncoder; // [1]

    @GetMapping("/encrypt_pw")
    public String securityPassword(@RequestParam("pw") String pw) {
        return passwordEncoder.encode(pw);
    }

}
  • [1] : passwordEncoder를 사용하여 암호화를 진행한다.

Controller TestCode

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

/**
 * ## Reference
 * - [1]. https://goodgid.github.io/Spring-Test-SpringBootTest-Annotation
 * - [2]. https://youngjinmo.github.io/2021/05/passwordencoder/
 * - [3]. https://velog.io/@hyeinisfree/SpringSecurity-PasswordEncoder
 */
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK) // [1]
@AutoConfigureMockMvc // [1]
class SecurityControllerTest {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private MockMvc mockMvc;

    @Test
    @DisplayName("패스워드 암호화 테스트")
    @WithMockUser(roles = "USER, ADMIN") // Spring Security 때문에 권한을 부여해줘야 테스트를 성공한다.
    void securityPasswordTest() throws Exception {
        // given
        String rawPassword = "12345678";
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("pw", rawPassword);

        // when
        ResultActions result = mockMvc.perform(get("/security/encrypt_pw")
                                                       .params(map));
        String contentAsString = result.andReturn().getResponse().getContentAsString();

        // then
        assertAll(
                () -> assertNotEquals(rawPassword, contentAsString),
                () -> assertTrue(passwordEncoder.matches(rawPassword, contentAsString))
        );
    }
}

Summary

  • PlainText를 암호화하는 코드와

    TestCode를 통해 정상적으로 암호화가 이뤄지는지까지 확인해봤다.

  • 이와 관련된 모든 코드는 Github을 참고하자.


Reference


Index