1.为什么会出现跨域无法访问的情况?
跨域是指不同域名之间的相互访问。当要在在页面中使用js获取其他网站的数据时,就会产生跨域问题,比如在网站中使用ajax请求其他网站的天气、快递或者其他数据接口时以及hybrid app中请求数据,浏览器就会提示以下错误。跨域是由浏览器的同源策略造成的(下面解释同源策略)。
2.什么是同源策略?
同源策略是浏览器的一种安全策略,所谓同源是指,域名,协议,端口完全相同。只要这四个任何一个不同,就不是同源了。
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据,防范跨站脚本的攻击,禁止客户端脚本(如 JavaScript)对不同域的服务进行跨站调用。
3.什么是跨域问题?
浏览器均默认开启了同源策略,它指Ajax请求所在的页面和被请求的页面在协议、域名、端口均相同才能被访问,否则会提示如下错误:
XMLHttpRequest cannot load xxxxxxx is not allowed by Access-Control-Allow-Origin.
4.怎么解决跨域问题?
4.1JSONP
JSONP全名是JSON with Padding。只支持get请求,不支持post请求。
基本原理:
JSONP通过动态的<script>元素来使用的,向服务器请求JSON数据(<script> 的src属性获得js代码, 不受同源政策限制),使用时为src属性指定一个跨域URL。
服务器收到请求后,将数据放在一个指定名字的回调函数(callback)里传回来。
用 JSONP 获取的不是 JSON 数据,而是可以直接运行的 JavaScript 语句。
下面是使用JSONP跨域请求的一个简单例子。
<script>
//回调函数
function checkName(result) {
document.getElementById("resultSpan").innerHTML=result.inner;
}
//监听用户名的变化
document.getElementById("name").onblur = function () {
var name = this.value;
//将回调函数名一起传到后台,后台无需操心实现功能的函数名,只要从前台获得即可
var resultStr = "http://168.168.4.69:3000/checkname?callback="+ "checkName" +"&username="+name;
//动态创建script
createScript(resultStr);
}
//动态创建script,用来实现jsonp的跨域请求
function createScript(src) {
var script=document.createElement("script");
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
</script>
总结简单流程:
动态生成<script>标签,然后通过标签的src属性发送GET类型的跨域请求,
服务器端返回一段js脚本,这段js脚本的内容为一个函数调用,实参为需要返回的响应数据(json),
客户端这边需要提前定义好对应的函数,当<script>请求成功并接收到数据时,会自动调用此函数,在函数中 我们就可以处理响应数据了.
4.2CORS(跨域资源共享)
CORS全名是Cross-Origin Resource Sharing(CORS)。跨域资源共享是一份浏览器技术的规范,以避开浏览器的同源策略,是 JSONP 模式的现代版。
与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。
用 CORS 可以让前端工程师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。
另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。CORS只能在现代的浏览器实现 。
基本原理:
使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
下面是显示CORS跨域的操作:
只需在服务器端添加一个响应头即可,
- 允许所有域都能访问:Access-Control-Allow-Origin: *
- 允许指定的域能访问:Access-Control-Allow-Origin: http://www.test.com
可以看出CORS实现非常简单,但是CORS存在一个缺陷,那就是兼容性问题。看图,IE8,9和opera Mini不支持