跨域问题是由于浏览器为了防止CSRF攻击,避免恶意攻击带来的风险而采用的同源策略限制。当一个页面中使用XMLHttpResquest对象发送HTTP请求时(XHR请求),必须保证当前页面和请求的对象是同源的,即协议、域名、端口号完全一致,否则浏览器就会阻止此跨域请求返回的数据。
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 是同源的
跨域请求的解决方案
1. JSONP:只支持GET,不支持POST请求
2. 代理:使用代理去避开跨域请求,例如www.a.com/index.html页面去调用www.b.com/service.jsp,可以通过写一个接口www.a.com/service.jsp,由这个接口在后端去调用www.b.com/server.jsp并取到返回值,然后再返回给index.html。
3. CORS:服务器端添加header限制。header('Access-Control-Allow-Origin:*'); //允许所有来源访问header('Access-Control-Allow-Method:POST,GET'); // 允许访问的方式
JSONP原理
浏览器对 XMLHttpRequest 请求和 img 标签有同源限制,而对 script 标签 src 属性、link 标签 href 属性没有这种限制。jsonp 就是利用 script 标签没有同源限制的特点来实现的。当第三方站点请求时,我们可以将此请求放在 <script> 标签的 src 属性里。
JSONP请求实现
1. js实现
服务器端:
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>
2. JQuery实现:JQuery的ajax方法对jsonp方法进行了封装。
前端:
<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>