使用 CORS 过滤器的跨源请求

Posted

技术标签:

【中文标题】使用 CORS 过滤器的跨源请求【英文标题】:Cross origin request with CORS filter 【发布时间】:2015-04-17 21:10:06 【问题描述】:

我正在尝试从 AngularJS 1.3 应用程序向 REST 服务发出跨源请求。虽然我启用了 CORS 过滤器,但我得到了 403 Forbidden 响应。这是请求(从 chrome 开发工具复制粘贴)。在 IE 9 上它似乎可以工作。我在 Chrome 和 Firefox 上收到 403 错误代码。

Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/<path>
Request Method:OPTIONS
Status Code:403 Forbidden
Request Headersview source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en,ro;q=0.8,en-US;q=0.6,en-GB;q=0.4
Access-Control-Request-Headers:x-auth-token, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, ike Gecko) Chrome/40.0.2214.111 Safari/537.36
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Origin, Accept, x-auth-token, Content-Type,        
Access-Control-Request-Method, Access-Control-Request-Headers
Access-Control-Allow-Methods:POST, GET, HEAD, OPTIONS
Access-Control-Allow-Origin:http://localhost:9000
Content-Length:0
Content-Type:text/plain
Date:Tue, 17 Feb 2015 07:11:24 GMT
Server:Apache-Coyote/1.1

网址没问题。如果我直接将它粘贴到浏览器中,它就可以工作。

跨域认证有效:

Remote Address:127.0.0.1:8080
Request        
URL:http://localhost:8080/<serviceName>/webapi/authentication/authenticate
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en,ro;q=0.8,en-US;q=0.6,en-GB;q=0.4
Connection:keep-alive
Content-Length:42
Content-Type:application/json;charset=UTF-8
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,     like Gecko) Chrome/40.0.2214.111 Safari/537.36
Request Payload
username: "user", password: "pass"
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:9000
Content-Length:100
Content-Type:application/json
Date:Tue, 17 Feb 2015 07:11:24 GMT
Server:Apache-Coyote/1.1
Set-Cookie:JSESSIONID=805B2490C0BA258D7D0FF4235BA49B76; Path=/<appcontext>/;     
HttpOnly

我正在使用 Spring Security 进行身份验证。对于跨源请求,我还需要什么?

使用的 CORS 过滤器:

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class CORSFilter2 implements Filter 

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
    

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse     servletResponse, FilterChain filterChain) throws IOException, ServletException 
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:9000");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, x-auth-token, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
        filterChain.doFilter(servletRequest, servletResponse);
    

    @Override
    public void destroy() 

    

【问题讨论】:

【参考方案1】:

通过 CORS 非GET 请求在浏览器中自动发送预检请求。您应该在 HTTP 服务器上允许 OPTIONS 方法,并且在 CORS 中允许标头为这些请求提供服务。您的服务器应使用 CORS 允许标头和 200 ok 响应预检的空响应正文。

根据您的 cmets,问题可能是由您的自定义 x-auth-token 标头引起的,该标头不是由 OPTIONS 请求发送的,因此您的服务器以 403 forbidden 响应。

预检调用是用于确定是否允许操作的调用。它 不应该需要凭据来确定我是否可以做某事,它 应该只需要凭据来实际执行它。

CORS preflight issues in Firefox and Chrome

我同意 Ryan 的观点,您不应该通过 OPTIONS 检查 auth 标头。

【讨论】:

OPTIONS 已被允许:Access-Control-Allow-Methods:POST、GET、HEAD、OPTIONS。在过滤器中我有: response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");在响应标头中,它显示为允许。 @MihaiSerban 是否在 HTTP 服务器上启用(例如在 htaccess/web.config 中)?你用 200 ok 处理它吗? 在 web.xml 中启用了 CORS 过滤器,这就是标题出现在响应中的原因。它被映射到使用的 url 模式。 @MihaiSerban 我想你误会了。这与 CORS 标头无关。您的服务器不提供 OPTIONS 请求的问题。您应该将其添加到路由并发送 200 ok 并带有空响应正文和 ofc。相同的 CORS 允许标头。顺便提一句。这个问题与rest和angular无关。 我设法通过删除 x-auth-token 来解决这个问题。这是正确的答案。【参考方案2】:

在预检 CORS 请求的情况下,您需要注意不会在 OPTIONS 请求中发送凭据。如果后者在其响应中发回正确的 CORS 标头,则使用凭证调用目标请求。这就是为什么你有 403 状态码...

所以你需要调整你的 CORS 过滤器,不要尝试验证这个 OPTIONS 请求。

除了上一个答案,这个链接可以帮助你解决你的问题:https://templth.wordpress.com/2014/11/12/understanding-and-using-cors/。

【讨论】:

是的,我绝对同意你的看法。我会看看我很老的答案来解决这个问题......感谢您指出这一点! 请不要在帖子中添加标语。 SE 确实不鼓励它,它不会在帖子中添加任何内容。

以上是关于使用 CORS 过滤器的跨源请求的主要内容,如果未能解决你的问题,请参考以下文章

允许对 http 和 https 的跨源请求

如何使用 Angular 2 在 POST 上启用 ASP.NET MVC 4 中的跨源请求

CORS 来源允许参数维护

为 API Gateway REST API 资源启用 CORS

Docker 容器的跨源错误

CORS