Skip to content

Instantly share code, notes, and snippets.

@jamilxt
Created April 8, 2025 06:32
Show Gist options
  • Save jamilxt/ed2b00a9d91476a345c8c3970db565ea to your computer and use it in GitHub Desktop.
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.
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