简介
- ajax 跨域只是浏览器"同源策略"中的一部分
ajax 跨域的原理
- 主要原因是因为浏览器的同源策略
CORS 请求原理
ajax 跨域的表现
第一种
- No ‘Access-Control-Allow-Origin’ header is present on the requested resource
The response had HTTP status code 404
- 本次ajax请求是“非简单请求”,所以请求前会发送一次预检请求(OPTIONS)
- 服务器端后台接口没有允许OPTIONS请求,导致无法找到对应接口地址
解决方案: 后端允许options请求
第二种
- No ‘Access-Control-Allow-Origin’ header is present on the requested resource
- The response had HTTP status code 405
- 后台方法允许OPTIONS请求,但是一些配置文件中(如安全配置),阻止了OPTIONS请求,才会导致这个现象
解决方案: 后端关闭对应的安全配置
第三种
- No ‘Access-Control-Allow-Origin’ header is present on the requested resource
status 200 - 这种现象和第一种和第二种有区别,这种情况下,服务器端后台允许OPTIONS请求,并且接口也允许OPTIONS请求,但是头部匹配时出现不匹配现象
- 比如origin头部检查不匹配,比如少了一些头部的支持(如常见的X-Requested-With头部),然后服务端就会将response返回给前端,前端检测到这个后就触发XHR.onerror,导致前端控制台报错
解决方案: 后端增加对应的头部支持
第四种
- heade contains multiple values ‘,’
- 表现现象是,后台响应的http头部信息有两个Access-Control-Allow-Origin:*
- 说实话,这种问题出现的主要原因就是进行跨域配置的人不了解原理,导致了重复配置,如:
常见于.net后台(一般在web.config中配置了一次origin,然后代码中又手动添加了一次origin(比如代码手动设置了返回*))
常见于.net后台(在IIS和项目的webconfig中同时设置Origin:*)
解决方案(一一对应):
- 建议删除代码中手动添加的*,只用项目配置中的即可
- 建议删除IIS下的配置*,只用项目配置中的即可
如何解决 ajax 跨域
- 客户端网页网页通过添加一个
<script>
元素,向服务器请求JSON数据,这种做法不受同源政策限制function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScriptTag('http://example.com/ip?callback=foo'); } function foo(data) { console.log('response data: ' + JSON.stringify(data)); };
- 服务端对应的接口在返回参数外面添加函数包裹层
foo({ "test": "testData" });
- 一般的JSONP接口和普通接口返回数据是有区别的,所以接口如果要做JSONO兼容,需要进行判断是否有对应callback关键字参数,如果有则是JSONP请求,返回JSONP数据,否则返回普通数据
- 基于JSONP的实现原理,所以JSONP只能是“GET”请求,不能进行较为复杂的POST和其它请求,所以遇到那种情况,就得参考下面的CORS解决跨域了
CORS 解决跨域问题
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1')
//这段仅仅为了方便返回json而已
res.header("Content-Type", "application/json;charset=utf-8");
if(req.method == 'OPTIONS') {
//让options请求快速返回
res.sendStatus(200);
} else {
next();
}
});
代理请求方式解决接口跨域问题
OPTIONS预检的优化
Access-Control-Max-Age:
这个头部加上后,可以缓存此次请求的秒数。
在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据。
非常有用,可以大幅优化请求次数
如何分析ajax跨域
抓包请求数据
- 接口返回的正确响应头域中包括
Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept Access-Control-Allow-Methods: Get,Post,Put,OPTIONS Access-Control-Allow-Origin: *
- 跨域错误的ajax请求
- 很多跨域错误基本都是类似的,都是三样没有满足 Headers,Allow,Origin