package net.gepafin.tendermanagement.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 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.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.servlet.util.matcher.MvcRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; import net.gepafin.tendermanagement.config.jwt.JWTFilter; import net.gepafin.tendermanagement.config.jwt.TokenProvider; @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) public class SecurityConfig { private final TokenProvider tokenProvider; @Autowired public SecurityConfig(TokenProvider tokenProvider) { this.tokenProvider = tokenProvider; } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { return new MvcRequestMatcher.Builder(introspector); } @Bean public WebSecurityCustomizer webSecurityCustomizer(MvcRequestMatcher.Builder mvc) { return (web) -> web.ignoring().requestMatchers(mvc.pattern(HttpMethod.OPTIONS, "/**")) .requestMatchers(new AntPathRequestMatcher("/i18n/**")) .requestMatchers(new AntPathRequestMatcher("/content/**")) .requestMatchers(new AntPathRequestMatcher("/swagger-ui/index.html")) .requestMatchers(new AntPathRequestMatcher("/swagger-ui/**")); } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.addAllowedMethod("*"); config.addAllowedHeader("*"); config.setMaxAge(3600l); if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) { source.registerCorsConfiguration("/v1/**", config); source.registerCorsConfiguration("/management/**", config); source.registerCorsConfiguration("/v1/api-docs", config); } return new CorsFilter(source); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth .requestMatchers(mvc.pattern(HttpMethod.POST, "/v1/user/login")).permitAll() .requestMatchers("/swagger-ui/**").permitAll() .requestMatchers("/v1/api-docs/**").permitAll() .anyRequest().authenticated() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .addServersItem(new Server().url("/")) .addSecurityItem(new SecurityRequirement().addList("bearer-key")) .components(new Components().addSecuritySchemes("bearer-key", new SecurityScheme().type(SecurityScheme.Type.HTTP) .scheme("bearer").bearerFormat("JWT"))); } }