跨域CORS

CORS全称是跨域资源共享(Cross-Origin Resource Sharing),用来解决AJAX跨域请求资源的问题

ajax跨域分析

// 这个js文件运行在localhost:8887中,ajax请求的url是localhost:9999/json,所以跨域了
let xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:9999/json', true);
xhr.send();

我们在浏览器发出一个ajax跨域请求的时候,通常会在控制台报下面的错误。

这个错意味着什么?是我们的请求没发出去吗?服务端有没有正常响应?其实真实情况是,这个请求发出去了,服务端也处理了这个请求,只是浏览器接收到了响应结果后发现这是个跨域请求,找不到对应的响应头(Access-Control-Allow-Origin),所以在控制台抛出了错误,代码中我们拿不到返回的结果

Access-Control-Allow-Origin

在服务端响应头设置Access-Control-Allow-Origin字段可以解决上面报错的问题

res.writeHead(200, {
  'Access-Control-Allow-Origin': '*'
});

如果要设置一个特定的域名才可以进行跨域请求,那么

res.writeHead(200, {
  // 设置只有从http://localhost:9999下发出的ajax请求才可以跨域
  'Access-Control-Allow-Origin': 'http://localhost:9999'
});

ajax跨域发请求的时候,分为简单请求和非简单请求

  • 简单请求

同时满足以下3个条件,会直接发送请求,就称为简单请求

  1. http的请求方法为get、post、head之一
  2. 请求头字段Content-Type为text/plain、multipart/form-data、application/x-www-form-urlencoded之一
  3. 没有自定义的头字段
  • 非简单请求

发正式请求前会发送一个预检options请求,当预检请求通过以后才会发真正的请求

下面是常见发送非简单请求的情况,还有其他情况,不一一列觉了

  1. 发请求时加入了自定义的头字段
  2. 发请求时的Content-Type头是application/json
  3. http请求的方法是put、delete等

Access-Control-Allow-Methods

举一个非简单请求的例子:

let xhr = new XMLHttpRequest();
// 注意这里是put方法,所以这个请求是非简单请求
xhr.open('put', 'http://localhost:9999/json', true);
xhr.send();

这个时候我们会发现浏览器报错了


看看chrome发送请求的情况

请求的方法是OPTIONS,请求头里浏览器自动添加了Access-Control-Request-Method:PUT,用来跟服务端验证PUT方法有没有被允许,由于我们服务端还没允许PUT方法,所以浏览器报错了

我们在响应里加个Access-Control-Allow-Methods就可以

res.writeHead(200, {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': 'http://localhost:8887',
    'Access-Control-Allow-Methods': 'PUT'//可以写多个,用逗号分开 
});

再来看看chrome发送的请求,第一个请求还是预检请求,预检请求通过发了第二个请求

由于这次服务端响应头返回了Access-Control-Allow-Methods: PUT,预检成功,然后发送了真正的PUT请求

但是对于非简单请求,如果每次都发预检请求太浪费了,可以通过设置Access-Control-Max-Age响应头控制缓存时间,单位是秒,在这个时间内不会在发预检请求了,nodejs中可以如下设置:

res.writeHead(200, {
    'Access-Control-Allow-Origin': '*'
    'Access-Control-Max-Age': 100 //100秒之内不发预检请求
});

Access-Control-Allow-Headers

有时候我们在发ajax的时候自定义了头信息

let xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:9999/json', true);
xhr.setRequestHeader('X-Cross-Test', 'test');//设置一个自定义头
xhr.send();

需要服务端需要返回允许这个头Access-Control-Allow-Headers才可以

res.writeHead(200, {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': 'http://localhost:8887',
    'Access-Control-Allow-Headers': 'X-Cross-Test'//可以是多个,用逗号分隔
});

Access-Control-Allow-Credentials

在浏览器发起一个http请求的时候,会默认带上该域名下的cookie,在跨域请求的时候,由于请求的是别的域名,不会带上别的域名的cookie,如果需要带上另一个域名的cookie信息,需要加个withCredentials=true

let xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:9999/json', true);
xhr.withCredentials = true;
xhr.send();

同样的,服务端要返回Access-Control-Allow-Credentials

res.writeHead(200, {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': 'http://localhost:8887',
    'Access-Control-Allow-Credentials': true
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、简介 CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。 整个CO...
    mongofeng阅读 2,286评论 0 0
  • $ 什么是CORS   CORS:Cross-Origin-Resource-Sharing:跨站点资源共享,是一...
    果汁凉茶丶阅读 10,357评论 2 19
  • http的客户端 最简单的http的客户端就是我们的浏览器,只要实现了发送一个http的请求的报文的工具,那么这就...
    kim_jin阅读 3,688评论 0 2
  • 出去溜达了一圈面试,发现很多公司爱问CORS技术,辣mo~这一节我们来研究下CORS吧 ~ 什么是跨域? 一个ur...
    monkeyying阅读 4,780评论 0 3
  • 1.构成跨域的条件(满足下方任意一个条件则构成跨域) domain不同(域名或者ip不同) 端口不同 ...
    imsjw阅读 5,878评论 0 0

友情链接更多精彩内容