Ajax-解决跨域请求(jsonp、cors)

概念

同源策略是浏览器的一种安全策略,所谓同源是指域名、协议(http、https)、端口完全相同,只有同源的地址才可以相互通过AJAX的方式请求。不同源地址之间,默认不能相互发送AJAX请求

同源或者不同源说的是两个地址之间的关系,不同源地址之间请求我们称之为跨域请求。

http://www.baidu.com:80和ftp://www.baidu.com:80                            不同域,协议不一样

http://www.baidu.com:80和http://www.xiaomi.com:80                        不同域,主机名不一样

http://www.baidu.com:80和ftp://www.baidu.com:8080                        不同域,端口号不一样

http://www.baidu.com:80/a.html和ftp://www.baidu.com:80/b.js           同域

 

跨域请求的前因后果

为什么浏览器要限制跨域请求,其中最主要的原因就是安全性问题,比如CSRF攻击。但是,既然不安全,为什么我们又要跨域请求呢?为了服务器便于管理和减轻服务器压力,公司会把不同的资源放在不同的服务器上,这样就存在很多子域,这时比如A子域的html资源要去访问B子域的图片资源就会出现跨域请求了。(可以注意下京东网站就是个很好的例子)

 

方法一、JSONP

ajax请求不同域会出现跨域请求,无访问权限

//报错CORS header ‘Access-Control-Allow-Origin’ missing
$.get("http://locally.uieee.com/categories", {},
    function (data, textStatus, jqXHR) {
        console.log(data)
    },
);

但平时在HTML页面写的<script>、<link>这些标签的src属性是不受跨域请求限制的。

var script = document.createElement('script')
script.src = 'http://locally.uieee.com/categories'//返回的是json
document.body.appendChild(script)

JSONP的策略就是服务器端可以动态生成JSON文件,把客户端需要的数据放到这个文件中,让客户端通过<script>标签的src属性来请求这个文件,这样,一种解决方案就出来了。

客户端 

 在任意位置写一个html页面

服务端    

在nodejs的express框架里的public写一个js文件,静态资源都放在这里。

双击打开.html文件可看结果

注意

JSONP方式无法发送POST请求,只能通过URL后面带参数实现,而且想要确定JSONP的请求是否失败并不容易,大多数实现都是结合超时时间来进行判断的。

 

方法二、CORS跨资源共享

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

这种方案无需客户端做出任何变化(客户端不用改代码),只是在被请求的服务端响应的时候添加一个响应头Access-Control-Allow-Origin,表示这个资源是否允许指定域请求。

服务器端设置

如需允许所有资源都可以访问的资源,可以如此设置:

Access-Control-Allow-Origin: *

如需允许https://developer.mozilla.org访问您的资源,可以设置:

Access-Control-Allow-Origin: https://developer.mozilla.org

Node.js 设置header解决跨域问题

//也可单独于某个请求中设置相应头
app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
    next();
});

//res.header()  是res.set()的别名,为express中的用法
//res.setHeader()为node无express用法

 

CORS和缓存

如果服务器未使用“*”,而是指定了一个域,那么为了向客户端表明服务器的返回会根据Origin请求头而有所不同,必须在Vary响应头中包含Origin

Access-Control-Allow-Origin: https://developer.mozilla.org
Vary: Origin

 

posted @ 2020-03-01 21:55  浮华而已-  阅读(1182)  评论(0编辑  收藏  举报