How to alter allowed headers in Spring Boot

2020-04-14 07:59发布

问题:

I'm currently using Auth0 (and an Angular 2 GUI), which sends a header of the type "x-xsrf-token" in the request to a Spring Boot API.

I get the error:

"XMLHttpRequest cannot load http://localhost:3001/ping. Request header field x-xsrf-token is not allowed by Access-Control-Allow-Headers in preflight response."

This is fair enough as the list of Access-Control-Response-Headers in Response Headers does not include x-xsrf-token (when debugging the request in the network tab in Chrome).

I have tried a number of solutions, the closest I think I have come is to override the configure method in AppConfig, and add in my own CorsFilter, like below:

(Imports removed for brevity)

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class AppConfig extends Auth0SecurityConfig {

    @Bean
    public Auth0Client auth0Client() {
        return new Auth0Client(clientId, issuer);
    }

    @Bean
    public Filter corsFilter() {
        UrlBasedCorsConfigurationSource source = new     UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("Content-Type");
        config.addAllowedHeader("x-xsrf-token");
        config.addAllowedHeader("Authorization");
        config.addAllowedHeader("Access-Control-Allow-Headers");
        config.addAllowedHeader("Origin");
        config.addAllowedHeader("Accept");
        config.addAllowedHeader("X-Requested-With");
        config.addAllowedHeader("Access-Control-Request-Method");
        config.addAllowedHeader("Access-Control-Request-Headers");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);

        return new CorsFilter(source);
    }

    @Override
    protected void authorizeRequests(final HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/ping").permitAll().antMatchers("/").permitAll().anyRequest()
            .authenticated();
    }

    String getAuthorityStrategy() {
        return super.authorityStrategy;
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.addFilterAfter(auth0AuthenticationFilter(auth0AuthenticationEntryPoint()),
            SecurityContextPersistenceFilter.class)
            .addFilterBefore(simpleCORSFilter(), Auth0AuthenticationFilter.class);
        authorizeRequests(http);http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.cors();
        }
    }

Unfortunately I have had no success with this, and still see the x-xsrf-token missing in the response header of my get request.

My base project is this: https://github.com/auth0-samples/auth0-spring-security-api-sample/tree/master/01-Authentication/src/main

Any ideas would be welcome.

回答1:

Ultimately I solved this myself. I removed this dependency here in the pom.xml file:

<dependency>
            <groupId>com.auth0</groupId>
            <artifactId>auth0-spring-security-api</artifactId>
            <version>0.3.1</version>
</dependency> 

because it is an open source project on github, here https://github.com/auth0/auth0-spring-security-api. I added the source code to my project in its own package, and added its dependencies to my pom.xml file. Then I changed the doFilter method in the Auth0CORSFilter to include my x-xsrf-token:

@Override
public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException {
    final HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
            "Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
    chain.doFilter(req, res);
}

Unfortunately, I now won't be able to switch versions as easily if I need to, I also have a slightly more cluttered codebase, however as I am new to Spring this was far easier than spending hours trying to override the Auth0CORSFilter Bean, if that was ever possible.



回答2:

Believe this is already under discussion on the issue you posted here but thought it worth replying on SOF since you have raised the question here too.

What you can do, is modify your AppConfig to override the CORS Filter setting from the default library config with your own updated CORS Filter implementation

I think in your case, this might be just appending x-xsrf-token to this line:

response.setHeader("Access-Control-Allow-Headers", "Authorization, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
                "Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

However, as i have stated in the github issue (linked above), if you send me your HAR file I can verify this is definitely the case and provides a working solution for you.



回答3:

try,

@Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new     UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");

        config.addAllowedHeader("*");       
        config.addAllowedMethod("*");        
        source.registerCorsConfiguration("/**", config);



        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;


    }

https://spring.io/blog/2015/06/08/cors-support-in-spring-framework