Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Security CORS

I have a problem with CORS filter on spring security URL's. It doesn't set Access-Control-Allow-Origin and other exposed header on URL's belonging to spring sec (login/logout) or filtered by Spring Security.

Here are the configurations.

CORS:

@Configuration @EnableWebMvc public class MyWebMvcConfig extends WebMvcConfigurerAdapter { ********some irrelevant configs************     @Override     public void addCorsMappings(CorsRegistry registry) {         registry.addMapping("/*").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT")                 .allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",                         "Access-Control-Request-Headers")                 .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")                 .allowCredentials(true).maxAge(3600);     } } 

Security:

@Configuration @EnableWebSecurity public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {     @Override     protected void configure(HttpSecurity http) throws Exception {         http                 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()                 .formLogin()                     .successHandler(ajaxSuccessHandler)                     .failureHandler(ajaxFailureHandler)                     .loginProcessingUrl("/authentication")                     .passwordParameter("password")                     .usernameParameter("username")                 .and()                 .logout()                     .deleteCookies("JSESSIONID")                     .invalidateHttpSession(true)                     .logoutUrl("/logout")                     .logoutSuccessUrl("/")                 .and()                 .csrf().disable()                 .anonymous().disable()                 .authorizeRequests()                 .antMatchers("/authentication").permitAll()                 .antMatchers("/oauth/token").permitAll()                 .antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')")                 .antMatchers("/user/*").access("hasRole('ROLE_USER')");     } } 

So, if I make a request to the url's which are not listened by security - CORS headers are set. Spring security URL's - not set.

Spring boot 1.4.1

like image 631
user1935987 Avatar asked Oct 27 '16 13:10

user1935987


People also ask

How do I enable CORS in Spring security?

2. Controller Method CORS Configuration. Enabling CORS is straightforward — just add the annotation @CrossOrigin.

How do you prevent CORS from spring boot?

To code to set the CORS configuration globally in main Spring Boot application is given below. Now, you can create a Spring Boot web application that runs on 8080 port and your RESTful web service application that can run on the 9090 port.

What is CORS configuration in spring boot?

Cross-Origin Resource Sharing (CORS) is an HTTP-header-based mechanism that allows servers to explicitly allowlist certain origins and helps bypass the same-origin policy. This is required since browsers by default apply the same-origin policy for security.


2 Answers

Option 1 (Use WebMvcConfigurer bean):

The CORS configuration that you started with is not the proper way to do it with Spring Boot. You need to register a WebMvcConfigurer bean. Reference here.

Example Spring Boot CORS configuration:

@Configuration @Profile("dev") public class DevConfig {      @Bean     public WebMvcConfigurer corsConfigurer() {         return new WebMvcConfigurerAdapter() {             @Override             public void addCorsMappings(CorsRegistry registry) {                 registry.addMapping("/**").allowedOrigins("http://localhost:4200");             }         };     }  } 

This will provide the CORS configuration for a basic (no security starter) Spring Boot application. Note that CORS support exists independent of Spring Security.

Once you introduce Spring Security, you need to register CORS with your security configuration. Spring Security is smart enough to pick up your existing CORS configuration.

@Override protected void configure(HttpSecurity http) throws Exception {     http         .cors().and()                        .... 

Option 2 (Use CorsConfigurationSource bean):

The first option I described is really from the perspective of adding Spring Security to an existing application. If you are adding Spring Security from the get-go, the way that is outlined in the Spring Security Docs involves adding a CorsConfigurationSource bean.

@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {      @Override     protected void configure(HttpSecurity http) throws Exception {         http             // by default uses a Bean by the name of corsConfigurationSource             .cors().and()             ...     }      @Bean     CorsConfigurationSource corsConfigurationSource() {         CorsConfiguration configuration = new CorsConfiguration();         configuration.setAllowedOrigins(Arrays.asList("https://example.com"));         configuration.setAllowedMethods(Arrays.asList("GET","POST"));         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();         source.registerCorsConfiguration("/**", configuration);         return source;     } } 
like image 157
The Gilbert Arenas Dagger Avatar answered Oct 10 '22 02:10

The Gilbert Arenas Dagger


Instead of using the CorsRegistry you can write your own CorsFilter and add it to your security configuration.

Custom CorsFilter class:

public class CorsFilter implements Filter {      @Override     public void init(FilterConfig filterConfig) throws ServletException {      }      @Override     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {         HttpServletResponse response = (HttpServletResponse) servletResponse;         HttpServletRequest request= (HttpServletRequest) servletRequest;          response.setHeader("Access-Control-Allow-Origin", "*");         response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");         response.setHeader("Access-Control-Allow-Headers", "*");         response.setHeader("Access-Control-Allow-Credentials", true);         response.setHeader("Access-Control-Max-Age", 180);         filterChain.doFilter(servletRequest, servletResponse);     }      @Override     public void destroy() {      } } 

Security config class:

@Configuration @EnableWebSecurity public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {      @Bean     CorsFilter corsFilter() {         CorsFilter filter = new CorsFilter();         return filter;     }      @Override     protected void configure(HttpSecurity http) throws Exception {         http                 .addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter                 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()                 .formLogin()                     .successHandler(ajaxSuccessHandler)                     .failureHandler(ajaxFailureHandler)                     .loginProcessingUrl("/authentication")                     .passwordParameter("password")                     .usernameParameter("username")                 .and()                 .logout()                     .deleteCookies("JSESSIONID")                     .invalidateHttpSession(true)                     .logoutUrl("/logout")                     .logoutSuccessUrl("/")                 .and()                 .csrf().disable()                 .anonymous().disable()                 .authorizeRequests()                 .antMatchers("/authentication").permitAll()                 .antMatchers("/oauth/token").permitAll()                 .antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')")                 .antMatchers("/user/*").access("hasRole('ROLE_USER')");     } } 
like image 20
mika Avatar answered Oct 10 '22 00:10

mika