对如何处理 CORS OPTIONS 预检请求感到困惑 [英] Confused about how to handle CORS OPTIONS preflight requests

查看:46
本文介绍了对如何处理 CORS OPTIONS 预检请求感到困惑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是跨域资源共享的新手,并试图让我的 web 应用程序响应 CORS 请求.我的 web 应用程序是在 Tomcat 7.0.42 上运行的 Spring 3.2 应用程序.

I'm new to working with Cross Origin Resource Sharing and trying to get my webapp to respond to CORS requests. My webapp is a Spring 3.2 app running on Tomcat 7.0.42.

在我的 webapp 的 web.xml 中,我启用了 Tomcat CORS 过滤器:

In my webapp's web.xml, I have enabled the Tomcat CORS filter:

<!-- Enable CORS (cross origin resource sharing) -->
<!-- http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CORS_Filter -->
<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>   

我的客户端(使用 AngularJS 1.2.12 编写)正在尝试访问启用了基本身份验证的 REST 端点.当它发出 GET 请求时,Chrome 首先预检请求,但收到来自服务器的 403 Forbidden 响应:

My client (written with AngularJS 1.2.12) is trying to access a REST endpoint with Basic Authentication enabled. When it makes it's GET request, Chrome is first preflighting the request, but is receiving a 403 Forbidden response from the server:

Request URL:http://dev.mydomain.com/joeV2/users/listUsers
Request Method:OPTIONS
Status Code:403 Forbidden
Request Headers:
   OPTIONS /joeV2/users/listUsers HTTP/1.1
   Host: dev.mydomain.com
   Connection: keep-alive
   Cache-Control: max-age=0
   Access-Control-Request-Method: GET
   Origin: http://localhost:8000
   User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36
   Access-Control-Request-Headers: accept, authorization
   Accept: */*
   Referer: http://localhost:8000/
   Accept-Encoding: gzip,deflate,sdch
   Accept-Language: en-US,en;q=0.8
Response Headers:
   HTTP/1.1 403 Forbidden
   Date: Sat, 15 Feb 2014 02:16:05 GMT
   Content-Type: text/plain; charset=UTF-8
   Content-Length: 0
   Connection: close

我不完全确定如何进行.默认情况下,Tomcat 过滤器 接受 OPTIONS 标头来访问资源.

I'm not entirely sure how to proceed. The Tomcat filter, by default, accepts the OPTIONS header to access the resource.

我认为问题在于我的资源(请求 URL)http://dev.mydomain.com/joeV2/users/listUsers 被配置为只接受 GET 方法:

The problem, I believe, is that my resource (the request URL) http://dev.mydomain.com/joeV2/users/listUsers is configured to only accept GET methods:

@RequestMapping( method=RequestMethod.GET, value="listUsers", produces=MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<User> list(){
    return userService.findAllUsers();
}

这是否意味着我必须让该方法/端点也接受 OPTIONS 方法?如果是这样,这是否意味着我必须明确地让每个 REST 端点接受 OPTIONS 方法?除了杂乱的代码,我很困惑这甚至是如何工作的.据我了解,OPTIONS 预检是让浏览器验证浏览器是否应该有权访问指定的资源.我理解这意味着在预检期间甚至不应该调用我的控制器方法.因此,将 OPTIONS 指定为可接受的方法会适得其反.

Does this mean that I must make that method/endpoint accept OPTIONS method as well? If so, does that mean I have to explicitly make every REST endpoint accept the OPTIONS method? Apart from cluttering code, I'm confused how that would even work. From what I understand the OPTIONS preflight is for the browser to validate that the browser should have access to the specified resource. Which I understand to mean that my controller method should not even be called during the preflight. So specifying OPTIONS as an accepted method would be counter-productive.

Tomcat 是否应该直接响应 OPTIONS 请求而不访问我的代码?如果是这样,我的配置中是否缺少某些内容?

Should Tomcat be responding to the OPTIONS request directly without even accessing my code? If so, is there something missing in my configuration?

推荐答案

我坐下来调试 org.apache.catalina.filters.CorsFilter 以找出请求被禁止的原因.希望这可以在未来帮助某人.

I sat down and debugged through the org.apache.catalina.filters.CorsFilter to figure out why the request was being forbidden. Hopefully this can help someone out in the future.

根据 W3 CORS 规范第 6.2 节预检请求,如果提交的任何标头与允许的标头不匹配,则预检必须拒绝该请求.

According to the W3 CORS Spec Section 6.2 Preflight Requests, the preflight must reject the request if any header submitted does not match the allowed headers.

CorsFilter 的默认配置 cors.allowed.headers(和你的一样)不包括随请求提交的 Authorization 标头.

The default configuration for the CorsFilter cors.allowed.headers (as is yours) does not include the Authorization header that is submitted with the request.

我更新了 cors.allowed.headers 过滤器设置以接受 authorization 标头,并且预检请求现已成功.

I updated the cors.allowed.headers filter setting to accept the authorization header and the preflight request is now successful.

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    <init-param>
        <param-name>cors.allowed.headers</param-name>
        <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization</param-value>
    </init-param>     
</filter>

当然,我不确定为什么 CORS 过滤器默认不允许 authorization 标头.

Of course, I'm not sure why the authorization header is not by default allowed by the CORS filter.

这篇关于对如何处理 CORS OPTIONS 预检请求感到困惑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆