为什么会有跨域这个问题的出现呢?
这要谈到浏览器的同源策略了,同源策略限制了不同源之间的资源进行交互,用于隔离潜在的恶意文件的安全机制,并且是浏览器最基本的安全机制(同源:协议、域名、端口均相同,localhost和127.0.0.1也属于跨域)。
如果没有同源策略的限制,假设您进入一个银行网站A,输入了账号密码进行登录,服务器端验证通过后会在响应头中添加Set-Cookie字段,在下次访问时,浏览器就会将cookie附加在http请求头字段Cookie中,服务器就知道您已经登录过,便不再验证了,如果在cookie信息还存在的情况下,您访问另一个网站B,如果它是一个恶意网站,在您不知情的情况下向网站A发起了请求,这就相当于不法网站B登录了您的账户,可以为所欲为了!
又比如一个钓鱼网站,模仿银行网站A(没有了同源策略的限制,钓鱼网站就可以很轻松的网站A的DOM),诱导您输入账户密码信息,然后就可想而知了......
那么怎么实现跨域呢?
关于解决跨域的问题,这里只记录部分实现方式:
CORS(Cross-origin resource sharing)跨域资源共享
CORS是处理跨域问题的标准做法,需要浏览器和服务器同时支持,CORS的整个通讯过程都是浏览器自动完成的,而实现通信的关键是服务器,只要服务器实现了CORS接口,就可以实现跨域通信。
CORS通信与ajax通信没有什么差别,浏览器一旦发现ajax请求跨域,就会自动添加一些头信息。浏览器将CORS请求分为两类:简单请求,非简单请求。
对于简单请求,其请求方法必须是HEAD,PUT,GET,请求头不能超过一下5种字段:Accept,Accept-Language,Content-Language,Last-Event-ID,Content-Type:只限于三个值application/x-www-form-urlencoded
、multipart/form-data
、text/plain。凡是不满足以上两种情况的都是非简单请求,浏览器对这两种请求的处理方式是不同的,
具体详情请参考阮一峰老师的博客http://www.ruanyifeng.com/blog/2016/04/cors.html
JSONP(JSON with padding)
JSONP是JSON的一种使用模式,可以让网页从别的网站获取资料,即跨域读取资料。
与CORS相比,JSONP只支持get请求,CORS支持所有类型的http请求。
JSON是一种数据格式,而JSONP是将这种数据格式在客户端和服务器端进行传输的方式,JSONP利用具有src属性的标签(比如<script>、<img>、<iframe>)实现跨域,因为它们可以用来请求不同源的文件,JSONP通过在请求文件的url中添加请求参数和callback,可以使服务器端将请求的数据通过JSON格式传入客户端的callback指定的函数中进行处理,比如下面的代码(参考文章http://www.cnblogs.com/wjlog/p/5903238.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>
使用jQuery实现jsonp调用:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script type="text/javascript" src=jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){//jQuery自动生成回调函数将数据传给success调用
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
},
error: function(){
alert('fail');
}
});
});
</script>
</head>
<body>
</body>
</html>
jQuery将jsonp封装进了ajax,当然,ajax也可以通过服务器端设置代理实现跨域
代理
请求是使用前端的域名,通过代理(Nginx 配置),将请求转发到真正的后端的域名上。
server{
# 监听8080端口
listen 8080;
# 域名是localhost
server_name localhost;
#只要是localhost:8080/api开头的,都转发到真正的服务端地址http://localhost:8888
location ^~ /api {
proxy_pass http://localhost:8888;
}
}
window.postMessage()
是H5的一个接口,专注实现不同窗口不同页面之间的跨域通讯
document.domain()
这种方式只适用于主域名相同,但子域名不同的iframe跨域,比如主域名http://ceshi.com:8080,子域名是 http://child.ceshi.com:8080,这时只需给两个页面指定一下document.domain = ceshi.com就可以访问各自的window对象了。