Created
April 8, 2025 06:32
-
-
Save jamilxt/ed2b00a9d91476a345c8c3970db565ea to your computer and use it in GitHub Desktop.
Configures security settings for a Spring Boot application using Spring Security. It includes custom filters, authentication providers, and defines security rules for both REST and web endpoints. The configuration supports JWT authentication and custom login/logout mechanisms.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dev.jamilxt.backend.config; | |
import dev.jamilxt.backend.constant.SecurityConstant; | |
import dev.jamilxt.backend.security.CustomSignInSuccessHandler; | |
import dev.jamilxt.backend.security.CustomUserDetailsService; | |
import dev.jamilxt.backend.security.JwtAuthenticationFilter; | |
import dev.jamilxt.backend.security.MobileNumberAuthenticationProvider; | |
import lombok.RequiredArgsConstructor; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.core.annotation.Order; | |
import org.springframework.http.HttpMethod; | |
import org.springframework.security.authentication.AuthenticationManager; | |
import org.springframework.security.authentication.AuthenticationProvider; | |
import org.springframework.security.authentication.ProviderManager; | |
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; | |
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.configurers.AbstractHttpConfigurer; | |
import org.springframework.security.config.http.SessionCreationPolicy; | |
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.session.ForceEagerSessionCreationFilter; | |
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |
import org.springframework.web.filter.ForwardedHeaderFilter; | |
import java.util.Arrays; | |
import java.util.List; | |
@Configuration | |
@EnableWebSecurity | |
@RequiredArgsConstructor | |
public class SecurityConfig { | |
private static final String[] REST_PUBLIC_URLS = {"/swagger-ui.html", "/api/auth/**", "/swagger-ui/**", | |
"/api-docs/**", "/api/verify/**", "/v3/api-docs/**", "/configuration/ui", "/swagger-resources/**", | |
"/configuration/security", "/webjars/**", "/verify*"}; | |
public static final String[] WEB_PUBLIC_URLS = {"v3/api-docs/**", "/static/**", "/error/**", "/swagger-ui/**", | |
"/api-docs/**", "/verify/**", "/v2/api-docs", "/configuration/ui", "/swagger-resources/**", | |
"/configuration/security", "/swagger-ui.html/**", "/webjars/**", "/images/**", "/build/**", "/dist/**", | |
"/docs/**", "/pages/**", "/plugins/**", "/admin/auth/sign-in/**", "/css/**", "/js/**"}; | |
private final PasswordEncoder passwordEncoder; | |
private final JwtAuthenticationFilter jwtAuthenticationFilter; | |
private final CustomUserDetailsService customUserDetailsService; | |
private final CustomSignInSuccessHandler customSignInSuccessHandler; | |
@Bean | |
@Order(1) | |
public SecurityFilterChain restJwtFilterChain(HttpSecurity http) throws Exception { | |
return http.csrf(AbstractHttpConfigurer::disable) | |
.addFilterBefore(new ForwardedHeaderFilter(), ForceEagerSessionCreationFilter.class) | |
.securityMatcher("/api/**") | |
.authorizeHttpRequests((authorize) -> authorize.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() | |
.requestMatchers(REST_PUBLIC_URLS).permitAll().anyRequest().authenticated()) | |
.cors(AbstractHttpConfigurer::disable).csrf(AbstractHttpConfigurer::disable) | |
.sessionManagement( | |
sessionManager -> sessionManager.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) | |
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) | |
.requiresChannel(channelRequestMatcherRegistry -> channelRequestMatcherRegistry | |
.requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null).requiresSecure()) | |
.build(); | |
} | |
@Bean | |
@Order(2) | |
public SecurityFilterChain webFilterChain(HttpSecurity http) throws Exception { | |
return http.csrf(AbstractHttpConfigurer::disable) | |
.addFilterBefore(new ForwardedHeaderFilter(), ForceEagerSessionCreationFilter.class) | |
.authorizeHttpRequests( | |
auth -> auth.requestMatchers(WEB_PUBLIC_URLS).permitAll().anyRequest().authenticated()) | |
.formLogin(form -> form.loginPage("/admin/auth/sign-in").usernameParameter("email") | |
.failureUrl("/admin/auth/sign-in?error=true").successHandler(customSignInSuccessHandler)) | |
.rememberMe(rememberMe -> rememberMe | |
.tokenValiditySeconds((int) SecurityConstant.SESSION_TOKEN_EXPIRATION_TIME) | |
.key(SecurityConstant.SECRET).rememberMeParameter("remember-me")) | |
.logout(logout -> logout.logoutRequestMatcher(new AntPathRequestMatcher("/admin/auth/sign-out")) | |
.logoutSuccessUrl("/admin/auth/sign-in?signOut=true").clearAuthentication(true) | |
.invalidateHttpSession(true).deleteCookies("JSESSIONID", "remember-me")) | |
.build(); | |
} | |
@Bean | |
public AuthenticationProvider daoAuthenticationProvider() { | |
var authProvider = new DaoAuthenticationProvider(); | |
authProvider.setUserDetailsService(customUserDetailsService); | |
authProvider.setPasswordEncoder(passwordEncoder); | |
return authProvider; | |
} | |
@Bean | |
public AuthenticationProvider mobileAuthenticationProvider() { | |
return new MobileNumberAuthenticationProvider(customUserDetailsService); | |
} | |
@Bean | |
public AuthenticationManager authenticationManager() { | |
List<AuthenticationProvider> providers = Arrays.asList(mobileAuthenticationProvider(), | |
daoAuthenticationProvider()); | |
return new ProviderManager(providers); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment