Skip to content

Commit 3cfa6c7

Browse files
committed
CROS实现跨域时授权问题
1 parent 69e82a4 commit 3cfa6c7

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

CROS/README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
##CROS实现跨域时授权问题
2+
3+
Response to preflight request doesn't pass access control check:
4+
No 'Access-Control-Allow-Origin' header is present on the requested resource.
5+
Origin 'null' is therefore not allowed access. The response had HTTP status code 403
6+
7+
###问题的提出
8+
如果我们访问的资源是不需要授权的,也就是在HTTP请求头中不包含authentication头那么以上做法就足够了。但是如果该资源是需要权限验证的,那么这个时候跨域请求的预检测option请求,由于不会携带身份信息而被拒绝。浏览器会报出401错误。错误信息如下:
9+
10+
Failed to load resource:
11+
the server responded with a status of 401 (Unauthorized)
12+
XMLHttpRequest cannot load http://localhost/api/test.
13+
Response for preflight has invalid HTTP status code 401
14+
15+
既然知道了问题的原因,答案也就很容易得出:对需要进行跨域请求的资源(api),当服务端检测到是OPTONS请求时候统统放行,给出HTTP.OK(200)的状态和必要的响应头,哪怕它是不带身份信息的。
16+
这个问题既可以通过编写对应的后端代码实现,也可以通过设置服务器配置文件实现。也就是如何设置响应头和返回200状态码的办法了。
17+
18+
###Spring+Shrio的解决方案
19+
shiro中可以在自己实现的身份验证filter中加入以下代码:
20+
21+
```Java
22+
@Override protected boolean preHandle(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; if(request.getMethod().equals(RequestMethod.OPTIONS.name())) { response.setStatus(HttpStatus.OK.value()); return false; } return super.preHandle(request, response); }
23+
```
24+
25+
shiro中AccessControlFilter提供了访问控制的基础功能;比如是否允许访问/当访问拒绝时如何处理等,也是我们一般自定义权限验证时候的一个父类,我们通过重写他的onPreHandle方法判断是否是option请求,如果是则设置相应状态,(响应头已经在之前文章中通过filter配置过了)返回false表示该拦截器实例已经处理了,将直接返回即可。
26+
27+
###Tomcat配置
28+
需要修改tomcat的全局web.xml文件在CATALINA_HOME/conf下,加入以下配置。
29+
30+
```Xml
31+
<filter>
32+
<filter-name>CorsFilter</filter-name>
33+
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
34+
</filter>
35+
<filter-mapping>
36+
<filter-name>CorsFilter</filter-name>
37+
<url-pattern>/*</url-pattern>
38+
</filter-mapping>
39+
```
40+
41+
###Nginx配置
42+
43+
add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,PUT,DELETE' always;
44+
add_header 'Access-Control-Allow-Credentials' 'true' always;
45+
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
46+
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,User-Agent,
47+
Keep-Alive,Content-Type,accept,origin,X-Requested-With' always;
48+
49+
if ($request_method = OPTIONS ) {
50+
return 200;
51+
}
52+
53+
###Apache配置
54+
55+
Header always set Access-Control-Allow-Origin "http://waffle"
56+
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"
57+
Header always set Access-Control-Allow-Credentials "true"
58+
Header always set Access-Control-Allow-Headers "Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With"
59+
60+
RewriteCond %{REQUEST_METHOD} OPTIONS
61+
RewriteRule ^(.*)$ $1 [R=200,L]
62+
63+
###js请求示例
64+
请求时候需要加上Authorization和Content-Type头。
65+
66+
$http({
67+
method: 'POST',
68+
url: scope.webdav.url,
69+
withCredentials: true,
70+
headers: {
71+
Authorization: 'Basic ' + btoa(user + ':' + password),
72+
'Content-Type': 'application/vnd.google-earth.kml+xml; charset=utf-8'
73+
},
74+
data: getKml()
75+
})
76+
77+
参考文章:[http://www.jujens.eu/posts/en/2015/Jun/27/webdav-options/](http://www.jujens.eu/posts/en/2015/Jun/27/webdav-options/)

0 commit comments

Comments
 (0)