I am trying to integrate spring mvc in existing spring rest project. Security for spring rest is working fine. When I tried to implement security for spring mvc with least priority order then it will only worked for rest api. If I have set priority order for spring mvc high then it will work for spring mvc but for rest api it will redirect to login page.
Here is my code snippet
//base class for spring security config
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig
I have a two static class
for spring mvc
@Configuration
@EnableWebSecurity
@Order(1)
public static class SecurityConfig extends WebSecurityConfigurerAdapter
for rest api
@Configuration
@EnableWebSecurity
@Order(2)
public static class ApiSecurity extends WebSecurityConfigurerAdapter
For spring mvc configuration
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/admin/login")
.defaultSuccessUrl("/admin/home",true)
.permitAll()
.and()
.logout()
.permitAll();
}
For Rest api configuration
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
// we don't need CSRF because our token is invulnerable
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
// Un-secure H2 Database
.antMatchers("/h2-console/**/**").permitAll()
.antMatchers("/auth/**").permitAll()
.antMatchers("/refresh/**").permitAll()
.antMatchers("/facebook/**").permitAll()
.antMatchers("/admin/**").permitAll()
.antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources",
"/configuration/security",
"/swagger-ui.html").permitAll()
.anyRequest().authenticated();
// Custom JWT based security filter
JwtAuthorizationTokenFilter authenticationTokenFilter = new JwtAuthorizationTokenFilter(userDetailsService(), jwtTokenUtil, tokenHeader);
httpSecurity
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// disable page caching
httpSecurity
.headers()
.frameOptions().sameOrigin() // required to set for H2 else H2 Console will be blank.
.cacheControl();
}
@Override
public void configure(WebSecurity web) throws Exception {
// AuthenticationTokenFilter will ignore the below paths
web
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath)
.antMatchers(HttpMethod.POST,
refresh)
// allow anonymous resource requests
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/*.js",
"/*.*.*",
"/**/**/*.*",
"/favicon.ico",
"/v2/api-docs",
"/configuration/ui",
"/swagger-resources",
"/configuration/security",
"/swagger-ui.html",
"/resources/**",
"/static/**"
)
// Un-secure H2 Database (for testing purposes, H2 console shouldn't be unprotected in production)
.and()
.ignoring()
.antMatchers("/h2-console/**/**");
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
Each WebSecurityConfigurerAdapter basically configures one SecurityFilterChain which by default will process all HTTP requests.
When there are multiple SecurityFilterChain , it will check each SecurityFilterChain one by one in priority order and the first that can process the request will be used.
As both SecurityFilterChain are configured to process all HTTP requests , the SecurityFilterChain with the higher priority order are always be used.
So simply change the SecurityFilterChain for the API to have a higher priority and configure it to process the URL start with the API endpoint :
@Configuration
@EnableWebSecurity
@Order(Ordered.HIGHEST_PRECEDENCE)
public static class ApiSecurity extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**");
//continue configure http ......
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With