Spring Boot: 3.2.2
Spring Security: 3.2.2
JDK: 21
build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
// JWT 관련 dependency
implementation 'io.jsonwebtoken:jjwt-api:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5'
// lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// MariaDB
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
SecurityConfig.java
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final CustomAuthenticationEntryPoint authenticationEntryPoint;
private final CustomAccessDeniedHandler accessDeniedHandler;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors((cors) ->
cors.configurationSource(corsConfigurationSource())
)
.csrf((csrf) ->
csrf.disable()
)
.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests((authorizeRequests) ->
authorizeRequests
.requestMatchers("/api/user", "/api/user/*").hasRole("FREE")
.requestMatchers("/api/auth", "/api/auth/*").permitAll()
.anyRequest().authenticated()
)
.formLogin((formLogin) ->
formLogin.disable()
)
.httpBasic((httpBasic) ->
httpBasic.disable()
)
.exceptionHandling((exceptionHandler) ->
exceptionHandler
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
)
;
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.setAllowCredentials(false);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
cors.configurationSource(corsConfigurationSource())
CorsConfigurationSource에서 어떤 옵션을 주는지 추가 필요csrf.disable())
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
authorizeRequests.requestMatchers("/api/user").hasRole("ROLE")
formLogin.disable()
httpBasic.disable()
exceptionHandler.authenticationEntryPoint(authenticationEntryPoint)
401 Unauthorized 에러가 발생하면 이 핸들러를 사용하여 예외를 처리한다.exceptionHandler.accessDeniedHandler(accessDeniedHandler)
403 Forbidden 에러가 발생하면 이 핸들러를 사용하여 예외를 처리한다.