我刚开始使用跨源资源共享并尝试让我的webapp响应CORS请求。我的webapp是在Tomcat 7.0.42上运行的Spring 3.2应用程序。
在我的webapp的web.xml中,我启用了Tomcat CORS过滤器:
<!-- 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响应:
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
我不完全确定如何继续。 The Tomcat filter, by default,接受OPTIONS标头以访问资源。
我认为,问题是我的资源(请求网址)http://dev.mydomain.com/joeV2/users/listUsers配置为仅接受GET方法:
@RequestMapping( method=RequestMethod.GET, value="listUsers", produces=MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<User> list(){
return userService.findAllUsers();
}
这是否意味着我必须使该方法/端点也接受OPTIONS方法?如果是这样,这是否意味着我必须明确地让每个REST端点接受OPTIONS方法?除了混乱的代码,我很困惑,甚至可以工作。根据我的理解,OPTIONS预检是指浏览器验证浏览器是否应该有权访问指定的资源。我理解这意味着在预检期间甚至不应该调用我的控制器方法。因此,将OPTIONS指定为可接受的方法会适得其反。
Tomcat是否应该直接响应OPTIONS请求而不访问我的代码?如果是这样,我的配置中是否缺少某些内容?
答案 0 :(得分:43)
我坐下来通过org.apache.catalina.filters.CorsFilter
进行调试,找出禁止请求的原因。希望这可以在将来帮助某人。
根据W3 CORS Spec Section 6.2 Preflight Requests,如果提交的标头与允许的标头不匹配,则预检必须拒绝该请求。
default configuration for the CorsFilter cors.allowed.headers
(与您一样)不包含随请求提交的Authorization
标头。
我更新了cors.allowed.headers
过滤器设置以接受authorization
标头,现在预检请求已成功。
<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
标头。
答案 1 :(得分:4)
我要尝试的第一件事是通过在模块上插入以下配置块来为您的http请求设置角度调度的公共标头:
.config(function($httpProvider){
$httpProvider.defaults.headers.common = {};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
})
这些应该默认设置,但我发现由于其他模块的任何覆盖或内部角度引导过程,我经常必须在我的配置中手动执行此操作。
您的CORS过滤器应该在服务器端足以允许这些类型的请求,但有时,您需要指定除起源之外的请求方法以及接受的内容类型。 tomcat文档有这个高级块,可以解决这些问题。
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<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</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
如果第一个不能自行运行,请尝试增强过滤器,尤其是:
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<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</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>