package com.example.jwtlogin.config;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) ->
web
.ignoring()
.requestMatchers("/main")
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()
);
}
@Bean
protected SecurityFilterChain webSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.formLogin(Customizer.withDefaults())
.authorizeHttpRequests(
authorize -> authorize
.requestMatchers("/join", "/auth/login")
.permitAll()
.requestMatchers("/member/**")
.hasRole("MEMBER")
)
.headers(
httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer
.frameOptions(
HeadersConfigurer.FrameOptionsConfig::sameOrigin
)
);
return httpSecurity.build();
}
}
PathRequest.toStaticResources().atCommonLocations()
StaticResourceLocation
Enum을 반환한다.
📝 ignore() vs permitAll()
ignore()
은 필터를 거치지 않고,permitAll()
은 필터를 거친다.CSRF
,XSS
,Clickjacking
등의 취약점으로부터 보호하기 위해서는HttpSecurity
에서permitAll()
을 하는 것이 권장된다.
HttpSecurity
구성 시, SecurityFilterChain
을 @Bean
등록하도록 권장되고 있다. authorizeHttpRequests()
: 특정 리소스에 대한 접근권한을 설정한다.Customizer.withDefaults()
: 기본 옵션으로 사용하려는 매개변수에 사용한다.
Spring Boot 3.x.x
버전 즉,Security 6.1.x
버전 부터는 기존에 썼던csrf()
,formLogin()
,headers()
와 같이 인수를 갖지 않는 메서드들은 전부 Deprecated 되었다.
CSRF protection
은 spring security
에서 default
로 설정된다.GET
요청을 제외한 상태를 변화시킬 수 있는 POST
, PUT
, DELETE
요청으로부터 보호한다.<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
📝 CSRF 공격이란?
- 웹 어플리케이션 취약점 중 하나로 인터넷 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만드는 공격
- XSS는 사용자(희생자)의 PC에서 스크립트가 실행되지만, CSRF는 서버에서 스크립트가 실행된다.
httpSecurity.csrf(AbstractHttpConfigurer::disable)
rest api
를 이용한 서버라면, session
기반 인증과는 다르게 stateless
하기 때문에 서버에 인증정보를 보관하지 않는다. rest api
에서 클라이언트는 권한이 필요한 요청을 하기 위해서는 요청에 필요한 인증 정보를(OAuth2
, jwt token
등)을 포함시켜야 한다.💡 서버에 인증정보를 저장하지 않으므로, CSRF protection을 굳이 사용할 이유가 없다.
출처
스프링 시큐리티 (Spring Security)
최신 Spring Security 사용법 - SecurityFilterChain
[Spring Boot] Spring Boot 3.x SecurityConfig 설정하기
Spring Boot 3.x + Security 6.x 기본 설정 및 변화
[스프링시큐리티] Spring Security 5.7 (WebSecurityConfigurerAdapter 에러해결방법)
[Spring Security] 정적 자원 ignore하기
[Spring]Spring security - CSRF란?, http.csrf().disable() ?
[spring] spring security를 이용한 JWT 로그인