聊聊跨域那些小事
来到公司一个多月了,终于开始有与后台交互的项目了,结果在测试接口的时候,遇到了跨域的问题,公司采用的是以JSONP为主,想想大学时候的后台暴力跨域。
跨域
跨域跨域,域,简单来说代指的就是域名,跨域就是指跨越域名,当然,对于URl,协议、域名、端口三者之间任意一个不同就是两个不同的域。
http://hughhe.cn和https://hughhe.cn 不是一个域
proxy
大学的时候,为了方便开发调试,开发项目的时候曾经采用这种方法,简单的说就是用代理服务器来转发请求,同源策略是浏览器自带的限制,只有前端发起的请求才会收到这个限制,所有只要将请求通过后台来发送就不会有跨域的问题了。
比如,前后端分别开发,然后想要测试的时候怎么办?在前端开发的机器上可以用node或者其他语言写一个简单的后台,用来转发ajax请求,前端的请求先发到node上,然后用node将这个请求转发到后台开发的机器上,达到跨域请求的目的。
JSONP
jsonp大概是最常用的跨域方法了,简单方便,尤其对于采用JQuery等框架来说,和正常的ajax没有太多区别,只需要修改以下dataType就行.
$.ajax({
type: "GET",
url: "http://hughhe.cn",
dataType: "jsonp",
jsonp: "callback",//jsonp的回调函数名的参数名(默认为:callback)
jsonpCallback:"dataHandler",//自定义的jsonp回调函数名称,没有的话会默认生成一个函数名,对应以下的success
success: function(data){
},
error: function(){
alert('fail');
}
});
JSONP说白了并不是ajax请求,它并没有任何XHR对象,发起的是script请求,这也是由于浏览器对于script和img这类的标签没有同源的限制,所以我们通过script标签来跨域请求,用js来实现也很简单,就是加载一个script文件。
//callback 函数
var dataHandler = function(data){}
//动态创建script
var script = document.createElement('script');
script.src = 'http://hughhe.cn?callback=dataHandler';
document.body.appendChild(script);
后台收到请求后会返回一个字符串:
dataHandler({'name':'hugh'})
返回给前端后就会执行这个回调函数。
注意:JSONP并不是XHR请求,更不是异步ajax请求,所以并没有GET,POST,DELETE之分,所有请求都以GET的方式进行,这也意味着传递的数据收到URL长度的限制。
CORS
曾经用过的暴力手段,在后台允许所有人访问这个资源,添加了Access-Control-Allow-Origin:*
当我们使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略时,会在请求头上添加:Origin,后台则会在响应头加上:Access-Control-Allow-Origin;浏览器判断该响应头中是否包含Origin的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
所以我们可以在后台返回的响应头中添加Access-Control-Allow-Origin:*,或者指定其他域名访问,”Access-Control-Allow-Origin”,”http://hughhe.cn” 这样就不会有跨域问题了,当然这样并不安全,建议只在调试的时候采用这种方法。
当使用这种方法时,在正式发送请求之前,浏览器会先发送一次option请求,用来判断实际发送的请求是否是安全,所以,请在后台允许option请求,否则跨域还是会失败的。
其他问题
1.当浏览器使用XMLHttpRequest对象提交请求时,会在请求头添加X-Requested-With标志,这代表着发出的是异步请求还是同步请求,值为XMLHttpRequest代表发出的是异步请求,然而在我跨域的时候,并没有带上这个标志,难道跨域不属于正常的异步请求?
2.当设置Access-Control-Allow-Origin:*,cookie是无法上传的,另外Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传