如何在 Spring Boot 中更改允许的标头

Posted

技术标签:

【中文标题】如何在 Spring Boot 中更改允许的标头【英文标题】:How to alter allowed headers in Spring Boot 【发布时间】:2017-03-05 07:33:59 【问题描述】:

我目前正在使用 Auth0(和 Angular 2 GUI),它将请求中的 "x-xsrf-token" 类型的标头发送到 Spring Boot API。

我得到错误:

"XMLHttpRequest 无法加载http://localhost:3001/ping。请求头 Access-Control-Allow-Headers 中的字段 x-xsrf-token 不允许 预检响应。”

这很公平,因为 Response Headers 中的 Access-Control-Response-Headers 列表不包括 x-xsrf-token(在 Chrome 的网络选项卡中调试请求时)。

我尝试了很多解决方案,我想我最接近的是覆盖AppConfig中的configure方法,并添加我自己的CorsFilter,如下所示:

(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();
        
    

不幸的是,我没有成功,并且仍然看到我的 get 请求的响应标头中缺少 x-xsrf-token

我的基础项目是这样的: https://github.com/auth0-samples/auth0-spring-security-api-sample/tree/master/01-Authentication/src/main

欢迎提出任何想法。

【问题讨论】:

【参考方案1】:

最终我自己解决了这个问题。我在 pom.xml 文件中删除了这个依赖:

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

因为是github上的开源项目,这里https://github.com/auth0/auth0-spring-security-api。我将源代码添加到我自己的包中的项目中,并将其依赖项添加到我的 pom.xml 文件中。然后我更改了 Auth0CORSFilter 中的 doFilter 方法以包含我的 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);

不幸的是,如果需要,我现在无法轻松切换版本,我的代码库也稍微杂乱一些,但是由于我是 Spring 新手,这比花费数小时尝试覆盖 Auth0CORSFilter 要容易得多比恩,如果可能的话。

【讨论】:

【参考方案2】:

相信这已经在讨论您发布的问题 here 但认为值得在 SOF 上回复,因为您也在这里提出了问题。

您可以做的是修改您的 AppConfig 以使用您自己更新的 CORS Filter implementation 覆盖 default library config 中的 CORS 过滤器设置

我认为在你的情况下,这可能只是将 x-xsrf-token 附加到这一行:

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");

但是,正如我在 github 问题(上面链接)中所述,如果您将您的 HAR 文件发送给我,我可以验证这绝对是这种情况,并为您提供一个可行的解决方案。

【讨论】:

你所有的链接都坏了:-/ 这并不奇怪,因为答案是 2 年前的 :)【参考方案3】:

试试,

@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

【讨论】:

恐怕我没有运气。启动服务器时没有错误,但是当我开始运行 GET 请求时,我不断收到相同的“x-xsrf-token”投诉。还是谢谢 我试过这个配置,就像@JackWooding 我发现它不起作用。然后,我尝试明确列出我在 addAllowedHeader 部分中使用的标头,尽管文档说明“*”被接受为通配符,但它仍然有效。我认为在处理这些标头的某个地方潜伏着某种错误,但我不太确定在哪里。

以上是关于如何在 Spring Boot 中更改允许的标头的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot + Security:设置允许的来源时没有 Access-Control-Allow-Origin 标头

Angular Spring Boot:重定向错误:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段 Content-Type

如何在 Spring Boot 中更改 Multipart 文件的最大大小?

如何在所有请求标头中传递授权令牌 - Spring Boot java

CORS Spring Boot 2.1.2 不发送访问控制标头

如何使用 Spring Boot 和 Angular 应用程序隐藏授权标头