java web项目使用CORS方法实现跨域请求方案

问题产生背景

需要实现这样一个需求,在当前站点中使用ajax发送一个请求到另一个站点获取数据。js中使用jquery的ajax如下:

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
     url:http://219.151.48.39:8085/kanms_appServer/operationer/login,
     data:{
     	"username": "test",
		"password": "test" 
     },
     type:'post',
     dataType:'json',
     success:function(data){
     	console.info(data);          	 
     });

结果在页面上出现以下错误提示:

1
2
3
XMLHttpRequest cannot load http://219.151.48.39:8085/kanms_appServer/operationer/login. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'null' is therefore not allowed access.

问题分析

网上查询得知原来是因为跨域的问题,javascript出于安全方面的考虑,不允许跨域调用其他页面的对象。

什么是跨域?
简单的理解就是因为javascript同源策略的限制,a.com域名下的js无法操作b.com或者c.a.com域名下的对象。更详细的说明可以看下表:

URL 说明 是否允许通信
http://www.a.com/a.js 
http://www.a.com/b.js
同一域名下 允许
http://www.a.com/lab/a.js 
http://www.a.com/script/b.js
同一域名下不同文件夹 允许
http://www.a.com:8000/a.js 
http://www.a.com/b.js
同一域名不同端口 不允许
http://www.a.com/a.js 
https://www.a.com/b.js
同一域名不同协议 不允许
http://www.a.com/a.js 
http://70.32.92.74/b.js
域名和域名对应ip 不允许
http://www.a.com/a.js 
http://script.a.com/b.js
主域相同,子域不同 不允许
http://www.a.com/a.js 
http://a.com/b.js
同一域名,不同二级域名(同上) 不允许(cookie这种情况下也允许访问)
http://www.cnblogs.com/a.js 
http://www.a.com/b.js
不同域名 不允许

经分析得知js中XMLHttpRequest对象不能加载跨域上的资源

解决办法

那么,怎样才能解决跨域访问资源的问题呢,主要有JSONPflashiframexhr2。这里介绍使用CORS(跨域资源共享,Cross-Origin Resource Sharing)的方法。

CORS原理:
CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

做法为:设置HTTP响应头Access-Control-Allow-Origin,指定服务器端允许进行跨域资源访问的来源域。可以用通配符*表示允许任何域的JavaScript访问资源,但是在响应一个携带身份信息(Credential)的HTTP请求时,Access-Control-Allow-Origin必需指定具体的域,不能用通配符。

这里使用Filter的方式给服务端的所有请求都加上Access-Control-Allow-Origin响应头,代码如下:

SimpleCORSFilter类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.ustcinfo.kanms.support;

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 SimpleCORSFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletResponse res = (HttpServletResponse)response;
		res.setHeader("Access-Control-Allow-Origin", "*");
		res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
		res.setHeader("Access-Control-Max-Age", "3600");
		res.setHeader("Access-Control-Allow-Headers", "x-requested-with");
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {

	}

}

web.xml中添加过滤器的配置

1
2
3
4
5
6
7
8
9

<filter>
	<filter-name>corsfilter-name>
	<filter-class>com.ustcinfo.kanms.support.SimpleCORSFilterfilter-class>
filter>
<filter-mapping>
	<filter-name>corsfilter-name>
	<url-pattern>/*url-pattern>
filter-mapping>

加上以上代码后,使用原来的ajax访问跨域服务端信息的Response Header如下:

1
2
3
4
5
6
7
Access-Control-Allow-Headers:x-requested-with
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:*
Access-Control-Max-Age:3600
Content-Type:application/json;charset=UTF-8
Server:Jetty(8.1.10.v20130312)
Transfer-Encoding:chunked

并且可以通过ajax访问跨域服务器的资源了,大功告成。


你可能感兴趣的:(java web项目使用CORS方法实现跨域请求方案)