转载自:https://www.cnblogs.com/zhaosq/p/10511633.html
跨域问题是由于浏览器为了防止CSRF攻击(Cross-site request forgery跨站请求伪造),避免恶意攻击而带来的风险而采取的同源策略限制。当一个页面中使用XMLHTTPRequest(XHR请求)对象发送HTTP请求时,必须保证当前页面和请求的对象是同源的,即协议、域名和端口号要完全一致,否则浏览器就会阻止此跨域请求返回的数据。
例如:
http://www.a.com 与 https://www.a.com 是不同源的,它们协议不同
http://www.a.com 与 http://www.b.com 是不同源的,它们域名不同
http://www.a.com:80 与 http://www.a.com:8080 是不同源的,它们端口号不同
http://www.a.com/test1.js 与 http://www.a.com/test2.js 是同源的
跨域请求的解决方案
虽然同源限制可以有效的防止网络上的恶意攻击,但是在实际开发应用中,我们往往需要从本站点向第三方站点发送XHR请求,这就需要有效的解决跨域问题,可以有以下几种:
(1)JSONP:只支持GET,不支持POST请求代理:使用代理去避开跨域请求,例如www.a.com/index.html页面去调用www.b.com/service.jsp,可以通过写一个接口www.a.com/service.jsp,由这个接口在后端去调用www.b.com/service.jsp并取到返回值,然后再返回给index.html。
(2)服务端修改:例如在服务端页面添加header限制:
header('Access-Control-Allow-Origin:*'); //允许所有来源访问
header('Access-Control-Allow-Method:POST,GET'); // 允许访问的方式
由于JSONP是最灵活,也是最常用的方式,这里主要讲解JSONP方式解决跨域问题。
JSONP原理
浏览器只对XHR(XMLHttpRequest)请求有同源请求限制,而对script标签src属性、link标签ref属性和img标签src属性没有这这种限制,利用这个“漏洞”就可以很好的解决跨域请求。JSONP就是利用了script标签无同源限制的特点来实现的,当向第三方站点请求时,我们可以将此请求放在<script>标签的src属性里,这就如同我们请求一个普通的JS脚本,可以自由的向不同的站点请求:
<script src="http://www.b.com/request?para1=1"></script>
JSONP请求实现
(1)Javascript实现
服务端:
public void ProcessRequest(HttpContext context) {
context.Response.ContentType = "text/plain";
//指定的回调函数名称
String callbackFuncName = context.Request.QueryString["callback"];
String reponseData = "test jsonp";
//回调脚本
String scriptContent = callbackFuncName + "('" + reponseData + "'";
context.Response.Write(scriptContent);
}
前端:
<script type="text/javascript" src="http://localhost/Service.ashx?callback=jsonpCallback" />
//回调函数
function jsonpCallback(content){
alert(content); }
</script>
运行的结果显示test jsonp,可以看出整个过程:
script标签设置src属性为请求的地址,并判断回调函数作为参数服务端构建JS脚本,传递返回给客户端的数据客户端在回调函数中解析服务器生成的数据
(2)JQuery实现
JQuery的ajax方法对JSONP方法进行了封装,使用JQuery提供的方法变得非常简单
前端:
<script type="text/javascript">
$.ajax({
type: "get",
async: false,
url: "http://localhost:8546/Service.ashx",
dataType: "jsonp",
success: function (data) {
alert(data);
},
error: function () {
alert('fail');
}
});
</script>