[Spring Security] 비밀번호 암호화

HJ·2023년 8월 6일
0

Spring Security

목록 보기
1/9
post-thumbnail

참고 : Spring Security 적용
참고 : Spring Security 설정


PasswordEncoder

회원가입 시 DB 에 사용자 정보를 저장해야 추후에 사용자가 로그인 할 때 사용될 수 있습니다. 하지만 비밀번호와 같이 중요한 정보들을 평문으로 저장한다면 큰일이 발생할 수도 있습니다. 그렇기에 비밀번호를 암호화해야하는데 이 떄 PasswordEncoder 가 사용됩니다.

Spring Security 의 모든 비밀번호 encoder 는 PasswordEncoder 인터페이스를 구현합니다. 이번에 사용할 구현체는 BCryptPasswordEncoder 인데 PasswordEncoder 의 비밀번호를 암호화하는 encode(), 평문 비밀번호와 암호화된 비밀번호를 비교하는 matches() 를 오버라이딩하여 암호화 기능을 제공합니다.




SecurityConfig

Spring Security 사용을 위한 Configuration Class 작성을 위해 WebSecurityConfigurerAdapter 를 상속받아 클래스를 작성하고 @EnableWebSecurity 어노테이션을 추가합니다.

@EnableWebSecurity 는 Spring Security 를 활성화하고, 웹 보안 설정을 구성하는데 사용됩니다. 이 어노테이션을 사용하면 SpringSecurityFilterChain 이 동작하여 요청을 인증하고 인가합니다.

WebSecurityConfigurerAdapter 에는 스프링 시큐리티의 웹 보안 기능의 초기화 및 설정들을 담당하는 내용이 담겨 있으며, configure() 메서드를 오버라이딩하여 설정할 수 있습니다

또한 내부적으로 getHttp() 메서드가 실행될 때 HTTPSecurity 클래스를 생성하게 됩니다. 이 때 HTTPSecurity 는 인증/ 인가 API 의 설정을 제공합니다.




HttpSecurity

설정 정보를 구성할 때 HttpSecurity 를 사용하는데 스프링 시큐리티의 대부분 설정은 HttpSecurity 로 하며 아래와 같은 설정을 할 수 있습니다.

  1. 리소스(URL) 접근 권한 설정

  2. 인증 전체 흐름에 필요한 Login, Logout 페이지 인증완료 후 페이지 인증 실패 시 이동페이지 등 설정

  3. 인증 로직을 커스텀하기위한 커스텀 필터 설정

  4. 기타 csrf, 강제 https 호출 등 거의 모든 스프링시큐리티의 설정




SecurityConfig 메서드

[ 회원가입 ]

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	// 비밀번호 암호화 시 사용할 BCryptPasswordEncoder 를 스프링 빈으로 등록
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    } 

	// Spring Security 설정을 위한 오버라이딩
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        http.csrf().disable().authorizeRequests()
                .antMatchers("/", "/signUp", "/login").permitAll()     // 설정된 url 의 접근을 인증없이 허용한다
                .anyRequest().authenticated();      // 모든 리소스가 인증을 해야만 접근이 허용된다


    }

}

.antMatchers("/", "/home").permitAll()

antMatchers 에는 URL 을 설정할 수 있으며 뒤에 붙은 permitAll() 의 의미는 antMatchers 에 설정한 URL 의 접근을 인증 없이 허용한다는 것입니다.

그렇게 되면 인증없이는 저기에 지정되지 않은 모든 URL 에 접근할 수 없기 때문에 회원만 접근할 수 있는 페이지를 url 로 접근하는 것을 통제할 수 있습니다.


antMatchers("/admin/**").hasAnyRole("ADMIN")

url 을 유저의 권한에 따라 통제할 수도 있는데 위의 코드는 antMatchers로 설정한 URL들은 ADMIN 권한의 유저만 접근할 수 있다는 의미입니다.


anyRequest().authenticated()

이 옵션은 모든 리소스가 인증을 해야만 접근이 허용된다는 뜻입니다. 보통 이 옵션 이전에 다른 설정을 완료하고 나머지에 위 옵션을 적용합니다.



[ 간단한 로그인 ]

아래 함수는 Fileter 나 Provider 같은 것들을 상속받아 구현하지 않고 스프링에서 기본적으로 제공하는 객체들을 사용할 때의 예시입니다. 굉장히 간단한 버전이니 메서드만 참고하시면 좋겠습니다.


@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()
                .formLogin()
                .loginPage("/login")    // 인증되지 않은 사용자가 접근했을 때 이동시킬 url
                .loginProcessingUrl("/login")   // POST 방식으로 login url 이 호출되면 실행된다
                .usernameParameter("id")    // 사용자를 찾기 위해 사용할 매개변수
                .passwordParameter("password")
                .defaultSuccessUrl("/userHome")
                .failureUrl("/login");
    }
}

formLogin()

로그인 Form 페이지를 사용하여 로그인하는 방식을 사용할 때 사용합니다.


loginPage()

인증되지 않은 사용자가 인증 없이 접근 불가능한 url 에 접근했을 때 이동시킬 url 을 지정합니다.


loginProcessingUrl()
  • 설정된 URL 로 POST 요청이 오면 UserDetailsService 를 구현한 구현체의 loadUserByUSername() 이 자동으로 시작됩니다. 그러므로 Controller 에 따로 로그인을 처리하는 메서드를 만들 필요가 없습니다.

usernameParameter("id")

UserDetailsService 의 loadUserByUsername() 에서 유저를 찾을 때 사용할 매개변수를 지정하는 것입니다. 저는 유저를 찾기 위해 id 란 값을 사용하였고, 이는 form input 태그의 name 이 id 인 태그가 있어야 가능합니다.


passwordParameter("password")

form 에서 password 를 나타내는 input 태그의 name 을 입력합니다. default 값은 password 입니다.


defaultSuccessUrl("/userHome")

로그인이 성공했을 때 요청할 URL 이며, GET 방식으로 요청됩니다. default 값은 / 입니다.


failureUrl("/login")

실패했을 때 요청할 URL 이며, 마찬가지로 GET 방식으로 요청됩니다.

0개의 댓글