【问题标题】:Response for preflight has invalid HTTP status code 401 - Spring预检响应具有无效的 HTTP 状态代码 401 - Spring
【发布时间】:2017-03-15 04:18:40
【问题描述】:

每个人。 我是 Angular 2 和 Spring Framework 的新手。 我正在尝试一个带有授权标头(基本身份验证)的简单获取请求。

我正在使用 Spring Boot (1.2.6.RELEASE),这也可能是相关的。 我的 CORS 配置如下所示。

@Component
public class SimpleCorsFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCorsFilter.class);

public SimpleCorsFilter() {
    log.info("SimpleCORSFilter init");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, authorization, x-auth-token");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}

这是从客户端看的样子

    this.headers.append('Authorization', 'Basic dXNlcjphZG1pbg==');
    return this.http
            .get(`http://localhost:8080/api/login?username=${username}`, {headers : this.headers} )
            .map(response => response.json().data as any);
}

我不断得到:

XMLHttpRequest 无法加载 http://localhost:8080/api/login?username=user。预检响应 具有无效的 HTTP 状态代码 401

请帮忙,我不知道我错过了什么...... 我已经检查了很多帖子,但无法到达那里......

【问题讨论】:

  • HTTP 401 表示由于缺少授权而无法满足您的请求,请检查是否正常
  • 能不能去掉response.setHeader("Access-Control-Allow-Credentials", "true");试试看?
  • @TharsanSivakumar,有同样的想法,谢谢

标签: java spring angular cors


【解决方案1】:

这可能会很晚,但这可以解决一些问题,经过长时间我找到了答案

public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    public void configure( WebSecurity web ) throws Exception
    {
        web.ignoring().antMatchers( HttpMethod.OPTIONS, "/**" );
    }
}

参考https://stackoverflow.com/a/45830981/3724760

【讨论】:

  • 这必须是最佳答案 - 经过数小时的 Spring 文档、github 和 SO 爬行后到达这里
  • 我花了几个小时才终于找到了这个答案。
【解决方案2】:

如果有人在使用 Spring Boot、Spring Security 和 angular 2/4 等客户端时遇到类似情况,我已经发布了调查结果 here

对于那些正在寻找简短答案的人,您必须配置两件事:

  1. 使用 Spring Boot,启用全局 CORS 的推荐方法是在 Spring MVC 中声明并结合细粒度 @CrossOrigin 配置为:

    @Configuration
    public class CorsConfig {
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                            .allowedHeaders("*");
                }
            };
        }
    }
    
  2. 然后,在使用 Spring Security 时,您还必须在 Spring Security 级别启用 CORS,以允许它利用在 Spring MVC 级别定义的配置:

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and()...
        }
    }
    

干杯!!!

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • @khelwood 更新了答案,但为什么要投反对票?这就像从封面判断一本书一样吗?如果我没有更新答案,我会很感激的。
【解决方案3】:

http 方法为 OPTIONS 时避免过滤并设置状态 200

if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
    response.setStatus(HttpServletResponse.SC_OK);
} else {
    chain.doFilter(req, res);
}

【讨论】:

  • 感谢@Eswar,我不再收到错误消息了。但是,忽略 OPTIONS 请求是一个好的实现吗?我问是因为我真的不知道。
  • 我们可以在没有过滤器的情况下验证请求标头并发送状态码。每当我们在标头中发送授权时,浏览器都会发出预检请求,因此我们只是在验证来源并抛出错误状态代码。忽略 OPTIONS 不会影响我们过滤的其他 http 方法,但我不确定它的实现是否良好。
猜你喜欢
  • 2018-07-01
  • 2017-07-02
  • 2023-04-10
  • 2018-10-02
  • 2018-06-17
  • 2016-11-14
  • 2016-09-16
  • 2017-11-22
  • 2016-09-14
相关资源
最近更新 更多