인증/권한 업무 규칙과 전환 불변식 추출 (codex-bais-final3-20260713-192718-BAIS-SPRING-ANA-AUTH-001)

This commit is contained in:
forge-bot 2026-07-13 10:30:31 +00:00
parent 51208857e9
commit cd37bbe7d1

View file

@ -0,0 +1,76 @@
package com.example.auth.config;
import com.example.auth.security.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
/**
* Security Configuration - preserves all AUTH-0XX invariants.
* AUTH-004: BCrypt cost factor 12
* AUTH-050/051: Public vs authenticated endpoints
* AUTH-052/053/054: Role-based access control
*/
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final CustomAuthenticationEntryPoint authenticationEntryPoint;
private final CustomAccessDeniedHandler accessDeniedHandler;
public SecurityConfig(
JwtAuthenticationFilter jwtAuthenticationFilter,
CustomAuthenticationEntryPoint authenticationEntryPoint,
CustomAccessDeniedHandler accessDeniedHandler) {
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
this.authenticationEntryPoint = authenticationEntryPoint;
this.accessDeniedHandler = accessDeniedHandler;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
requestHandler.setCsrfRequestAttributeName("_csrf");
http
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.csrfTokenRequestHandler(requestHandler)
.ignoringRequestMatchers("/auth/login", "/auth/refresh")
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.sessionFixation().migrateSession()
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/login", "/auth/refresh").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/users/**").hasAnyRole("MANAGER", "ADMIN")
.requestMatchers("/reports/**").authenticated()
.anyRequest().authenticated()
)
.exceptionHandling(ex -> ex
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12); // AUTH-004
}
}