2

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;
}
Ken Chan
  • 84,777
  • 26
  • 143
  • 172
Bibek Shakya
  • 1,233
  • 2
  • 23
  • 45

1 Answers1

7

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 ......
        }

}
Ken Chan
  • 84,777
  • 26
  • 143
  • 172