오늘 스프링 시큐리티를 학습했다.
많은 학습량이기에 한번에 이해하기에는 욕심었기에 쪼개서 학습을 하기로 결정하였다.
자주 사용하는 용어 정리(알아두면 확실히 도움 된다.)
- Principal(주체) : 인증된 사용자의 계정 정보
- Authentication(인증) : 애플리케이션을 사용하는 사용자가 본인이 맞는지 확인하는 절차
- Credential : 사용자를 식별하는 정보
- Authorization(권한부여) : 인증통과한 사용자에게 권한을 부여하여 특정 리소스에 접근할 수 있도록 허가
- Access Control(접근 제어) : 사용자의 리소스 접근 행위를 제어하는 것
1) 의존 라이브러리 추가
implementation 'org.springframework.boot:spring-boot-starter-security'
2) Configuration을 통한 인증 방식 설정
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfiguration {
!! 이곳에 인증과 권한 부여를 설정하면 됩니다. !!
}
3) HTTP 보안 구성 기본
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// HttpSecurity를 통해 HTTP 요청에 대한 보안 설정을 구성한다.
...
...
}
HttpSecurity : HTTP 요청에 대한 보안 설정을 구성하기 위한 핵심 클래스
알아두면 좋은 내용
Spring Security 5.7 이전 버전에서는 HTTP 보안 설정을 하려면
WebSecurityConfigureAdapter를 상속하는 방식을 사용했다.
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
}
}
현재는 SecurityFilterChain을 Bean으로 등록해서 HTTP 보안 설정을 구성하는 방식을 권장한다.
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
return http.build();
}
}
다시 보안 구성 파트로...
@Configuration
public class SecurityConfiguration {
//(1)
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
//H2 웹 콘솔을 정상적으로 사용하기 위한 설정
.headers().frameOptions().sameOrigin()
.and()
.csrf().disable() //(1)CSRF 공격에 대한 Spring Security에 대한 설정을 비활성화
.formLogin() //(2) 기본적인 인증 방법을 폼 로그인 방식으로 지정
.loginPage("/auths/login-form") //(3) 로그인 페이지 설정
.loginProcessingUrl("/process_login") //(4) 로그인 인증 요청을 수행할 요청 URL
.failureUrl("/auths/login-form?error") // (5) 실패하면 어느 페이지로 이동할지
.and() // (6)
//7,8,9 를 통해 클라이언트의 요청에 대헤 접근권한 확인. 접근 허용할지 여부 결정
// .authorizeHttpRequests()//(7) 요청이들어오면 접근 확인하겠다!
//8,9 메서드를 통해 클라이언트의 모든 요청에 대해 접근을 허용하겠다.
// .anyRequest() // (8)
// .permitAll(); //(9)
.logout() //로그아웃 설정을 먼저 해준다.
.logoutUrl("/logout") // 로그아웃 url 지정
.logoutSuccessUrl("/") // 로그아웃 성공시 url 지정
.and()
//접근 권한이 없는 사용자의 접근이 있으면 403에러 처리하기 위한 페이지로 이동
.exceptionHandling().accessDeniedPage("/auths/access-denied")
.and()
//람다식을 통해 request URI에 대한 접근 권한 부여
.authorizeHttpRequests(authorize -> authorize
.antMatchers("/orders/**").hasRole("ADMIN")
.antMatchers("/members/my-page").hasRole("USER")
.antMatchers("/**").permitAll()
);
return http.build();
}
- headers().frameOptions().sameOrigin() : <'frame'>이나 <'iframe'>, <'object'> 태그에서 페이지를 렌더링 허용 X
- csrf().disable() : csrf 공격해도 뭐 상관없음. 이런건데 학습용이기에 설정한 것이다.
- formLogin() 기본적인 인증 방법을 폼 로그인 방식 지정
- loginPage("url") : 로그인 페이지 설정
- loginProcessingUrl("url") : 로그인 인증 요청을 수행할 요청 URL
- failureUrl("url") : 로그인 실패시 어느 페이지로 이동 여부 설정
- authorizeHttpRequests() : 요청 시 접근 확인
- anyRequest() + permitAll() : 모든 요청에 대한 허용 -> 현업에서 사용x
- logout() : 로그아웃 설정
- logoutUrl("url") : 로그아웃 url 설정
- logoutSuccessUrl("url") : 로그아웃 성공시 이동할 url 설정
- exceptionHandling().accessDeniedPage("url") : 접근 권한이 없는 사용자의 접근이 있을 때 해당 페이지로 이동
- authorizeHttpRequests : 람다식을 통해 request URI에 대한 접근 권한 부여
- andMatchers("/orders/).hasRole("ADMIN") : /orders/ 주소 이용자는 ADMIN만 가능
- andMatchers("/members/my-page).hasRole("USERS") : 로그인한 유저만 마이페이지 사용 가능