为什么会出现跨域
跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题,比如a标签、script标签、甚至form标签(可以直接跨域发送数据并接收数据)等
Cross-Origin Resource Sharing(CORS) 是W3C为浏览器制定的可以跨域通信的规范. 通过使用 XMLHttpRequest 对象, CORS可以让开发者方便的进行跨域通信, 就像在使用同域通信一样.
发送一个跨域请求:
根据浏览器的同源策略, 当请求的地址与来源地址的协议\域名\端口中的任一值不相同时, 均视为是一个跨域的请求.
XMLHttprequest 的 withCredentials 属性
跨域请求通常不会携带cookies信息. 为了能让跨域请求带上cookies, 你需要将做如下设置:
xhr.withCredentials = true;
Access-Control-Allow-Credentials: true
设置withCredentials为true后, 在于服务器进行通信时会携带这个域名下的所有cookies, 同时服务器也可以在它的于域名下设置cookies. 但值得注意的是, 这些cookies仍然遵守浏览器的同源策略, 你无法通过javascript访问这个域名下的cookies, 它只被这个域名的服务器控制.
我们熟知的一个跨域通信的解决方式JSON-P就是利用GET发送一个简单请求来规避跨域的问题
所有的跨域请求(无论简单或者非简单)总会包含一个Origin的请求头部, 这个属性的值由浏览器添加, 而且不受用户控制. 它的值由协议(如: http), 域名(如: a.om)和端口(只有它不是默认值时才包含, 如80端口)组成, 说明请求的来源.
包含Origin的请求不一定是跨域请求, 但是跨域请求一定包含Origin. 一些同源的请求同样也会包含Origin请求头.
解决跨域问题的三种方式:
JSONP
JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
page:
function kunyu(){
$ajax({
url:'http:www.baidu.com',
type:'get',
dataType:'jsonp',
jsonpCallback:'mykuayu',
success:function(data){
console.info("data");
}
})
}
controller:
@requestMapping("/kuayu")
public String kuayu(HttpServletRequest request){
//callback的名称,由于前台没有指定callback函数,所以这里自动生成了,如果想自定义回调函数名称如下操作,添加一行请求参数
String callback = request.getParamter("callback");
return callback +"('kuayu')";
}
添加响应头,允许跨域
addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
controller层加入[允许跨域]:
httpResponse.addHeader("Access-Control-Allow-Origin","*");
代理的方式
服务器A的test01.html页面想访问服务器B的后台action,返回“test”字符串,此时就出现跨域请求,浏览器控制台会出现报错提示,由于跨域是浏览器的同源策略造成的,对于服务器后台不存在该问题,可以在服务器A中添加一个代理action,在该action中完成对服务器B中action数据的请求,然后在返回到test01.html页面。