참고 : Spring Security 적용
참고 : Spring Security 설정
회원가입 시 DB 에 사용자 정보를 저장해야 추후에 사용자가 로그인 할 때 사용될 수 있습니다. 하지만 비밀번호와 같이 중요한 정보들을 평문으로 저장한다면 큰일이 발생할 수도 있습니다. 그렇기에 비밀번호를 암호화해야하는데 이 떄 PasswordEncoder 가 사용됩니다.
Spring Security 의 모든 비밀번호 encoder 는 PasswordEncoder 인터페이스를 구현합니다. 이번에 사용할 구현체는 BCryptPasswordEncoder 인데 PasswordEncoder 의 비밀번호를 암호화하는 encode()
, 평문 비밀번호와 암호화된 비밀번호를 비교하는 matches()
를 오버라이딩하여 암호화 기능을 제공합니다.
Spring Security 사용을 위한 Configuration Class 작성을 위해 WebSecurityConfigurerAdapter 를 상속받아 클래스를 작성하고 @EnableWebSecurity
어노테이션을 추가합니다.
@EnableWebSecurity
는 Spring Security 를 활성화하고, 웹 보안 설정을 구성하는데 사용됩니다. 이 어노테이션을 사용하면 SpringSecurityFilterChain 이 동작하여 요청을 인증하고 인가합니다.
WebSecurityConfigurerAdapter 에는 스프링 시큐리티의 웹 보안 기능의 초기화 및 설정들을 담당하는 내용이 담겨 있으며, configure()
메서드를 오버라이딩하여 설정할 수 있습니다
또한 내부적으로 getHttp()
메서드가 실행될 때 HTTPSecurity 클래스를 생성하게 됩니다. 이 때 HTTPSecurity 는 인증/ 인가 API 의 설정을 제공합니다.
설정 정보를 구성할 때 HttpSecurity 를 사용하는데 스프링 시큐리티의 대부분 설정은 HttpSecurity 로 하며 아래와 같은 설정을 할 수 있습니다.
리소스(URL) 접근 권한 설정
인증 전체 흐름에 필요한 Login, Logout 페이지 인증완료 후 페이지 인증 실패 시 이동페이지 등 설정
인증 로직을 커스텀하기위한 커스텀 필터 설정
기타 csrf, 강제 https 호출 등 거의 모든 스프링시큐리티의 설정
@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()
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 방식으로 요청됩니다.