总结-使用CORS解决跨域问题

对前端来说跨域应该是不陌生的,解决跨域的方案有很多种。而我司前端接口调用也正是CORS的方式,所以难免在联调阶段会遇见一些CORS跨域的问题,下面通过一个简单的demo验证一下CORS解决跨域的过程中,对一些不清楚的知识点做一个简单的总结

示例 demo 已经放在GitHub 上, 其中目录client文件夹托管客户端代码、server目录作为处理CORS的服务端,分别把两端的代码跑起来,就可以进行CORS相关配置的学习了。

对CORS的了解可以先看下一下阮老师的这两篇文章:

1、浏览器同源政策及其规避方法
2、跨域资源共享CORS详解

假设你已经了解服务端处理CORS跨域时,会配置相关的一些响应头,如下:

Access-Control-Allow-Credentials: true,
Access-Control-Allow-Origin: *,
Access-Control-Allow-Headers: 'header',
Access-Control-Expose-Headers: 'serve-header',
Access-Control-Allow-Methods: 'methods',
Access-Control-Max-Age: '1800', // 30min = 1800s

那这些响应头都具体是神马作用呢?下面会结合demo来了解各参数的配置作用,并给出结果图。

第一个参数:Access-Control-Allow-Origin

作用:服务端允许跨域的源,也就是浏览器的输入的地址。demo中为:http://huoyun-test.djtest.cn 包括端口号80,80端口默认省略了。

如果把server端的origin改为: http://huoyun-online.djtest.cn, 当发送请求的时候,浏览器包如下错误:

如上图由请求头和响应头以及控制台(1、2、3)三点得出:由于CORS策略,通过浏览器预检请求options得出源Origin对应的url不在CORS跨域允许的范围内,因此呢,服务端应该设置对应的页面域名http://huoyun-test.djtest.cn,这样才不会报这样的错误。

第二个参数:Access-Control-Allow-Credentials

作用:携带cookie

如果调用接口过程中,需要cookie的传递,则需要设置这个参数为true,并且Access-Control-Allow-Origin就不能设为星号*,必须指定明确的、与请求网页一致的域名。如果前端采用axios来请求接口时,需同时设置axios.defaults.withCredentials = true;

这里如果设置 Access-Control-Allow-Origin: * ,会报如下的错误:

也就是上面说的Access-Control-Allow-Origin此时不能设置为星号*,如果不需要携带cookie时即不设置Access-Control-Allow-Credentials响应头,但此时前端设置了axios.defaults.withCredentials=true;,浏览器也会包类似的错误:

即当浏览器通过XMLHttpRequest对象发送请求时,设置了withCredentials属性为true时,对应的服务端此时需要做相应的处理。

因此当前后端在CORS跨域出现问题时,通过修改demo来验证就可以很好的找到答案了,而不是百度了一遍,依然是处于茫然中,不知道要让服务端干嘛,同时作为前端应该怎么做,不让自己此时成为前端小白,有话可说...

第三个参数:Access-Control-Allow-Headers

作用:前后端需要通过header来进行数据交互时,需要设置使用到的header字段。

如前端通过设置请求头header中的字段axios.defaults.headers.common['client-header'] = 1;, 如果此时Access-Control-Allow-Headers字段没有设置对应的header字段,浏览器会报如下错误:

也就是说通过前端设置的自定义header字段,需要服务端在Access-Control-Allow-Headers字段中设置对应的header

第四个参数:Access-Control-Expose-Headers

作用:允许浏览器端能够获取相应的header值

如果服务端接口设置了响应头字段res.setHeader('serve-header','from->express'); 但是CORS中对应的字段Access-Control-Expose-Headers并没有处理,此时通过请求响应后的header结果如下:

可以看到虽然响应头里面有serve-header字段,但是却获取不到, 如果设置了 Access-Control-Allow-Headers: serve-header再来看下结果:

此时则可以拿到服务端设置的响应头里面的serve-header字段了

第五个参数:Access-Control-Max-Age

作用:控制发送预检请求options的频率

1、如果设置Access-Control-Max-Age: 0, 则发送请求的时候浏览器始终都会先发送预检请求options。如图

每次点击send cors按钮请求接口 api/getcors 时,都会发送options预检请求

2、如果设置Access-Control-Max-Age: 1800, //预请求缓存30分钟=1800秒 结果如下:


对应的响应头:

点击send cors按钮请求接口 api/getcors 时,只会首次发送options预检请求,接着后面再次请求时就不会发options请求了

3、在2的基础上,如果你的Chrome浏览器在debug状态,勾选上Disable cache,也是失效的 如下:

即每次都会发送预检请求

4、这里强调一下Access-Control-Max-Age:1800设置缓存时间,仅仅是针对已经请求过的接口如api/getcors,当点击按钮send cors2 第一次请求接口api/getcors2时,同样也会发送预检请求options

第六个参数:Access-Control-Allow-Methods

作用:请求方法的限制

这里最后一个参数就留给读者你去校验了,修改下Access-Control-Allow-Methods 参数看看浏览器的报错结果,体会一下...

到这里6个参数就总结完了,下面补充一下CORS跨域时,cookie的携带过程

CORS跨域中cookie的携带

首 先Cookie操作具有不可跨域特性,如:
// client 端设置
Cookies.set('cookie-value', '1', { domain: 'huoyun-test.djtest.cn' });
Cookies.set('cookie-value', '2', { domain: 'test.djtest.cn' });
Cookies.set('cookie-value', '3', { domain: 'djtest.cn' });


// server 端设置
res.setHeader('Set-Cookie', 'cookie-value=22;domain=.test.djtest.cn;path=/');

打开chrom调试工具,如下:

即:页面huoyun-test.djtest.cn不可以操作test.djtest.cn的cookie,通过document.cookie读取的时候是可以获取到从一级域名djtest.cn 及以下的所有子域的cookie值,而在面板中是看不见服务端设置的cookie-value=22;domain=.test.djtest.cn;path=/的值,这里注意下!!!

那此时再请求接口api/getcors,服务端接受到的cookie值以哪个为准呢 ?如下:

即:最终解析到的cookie会以client端一级域名设置的值Cookies.set('cookie-value', '3', { domain: 'djtest.cn' }); 为准

最后

对于express中间件cors、以及cookie-parser的解析代码都不复杂,想了解的同学,欢迎clone 下来debug一下,印象会深刻点。demo地址如下:https://github.com/caoyongxi/cors-demo

推荐阅读

一文弄懂Nginx的location匹配

好文我在看????

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用CORS解决跨域问题的具体方法包括:首先,在服务器端设置 Access-Control-Allow-Origin 允许跨域请求;其次,在客户端使用 XMLHttpRequest 对象发起跨域请求;最后,在服务器端返回 Access-Control-Allow-Origin 响应头,以允许跨域访问。 ### 回答2: 跨域问题是由于浏览器的同源策略引起的,为了解决这个问题,可以使用CORS(Cross-Origin Resource Sharing)来进行跨域资源共享。CORS是一种机制,它允许网页服务器进行跨域访问控制,从而使跨域数据传输成为可能。 下面是使用CORS解决跨域问题的具体方法: 1. 在服务端设置Access-Control-Allow-Origin响应头来指定允许的源,允许的值可以是具体的域名、通配符(如*)或null。如果需要指定多个源,可以使用逗号分隔。 2. 如果请求需要携带身份凭证(如cookies、HTTP认证等),则还需要设置Access-Control-Allow-Credentials响应头为true。 3. 如果跨域请求包含自定义的请求头字段,浏览器会首先发送一个预检请求(OPTIONS)来获取服务器的CORS配置。服务器收到预检请求后,需要设置Access-Control-Allow-Methods响应头来指定允许的请求方法,以及Access-Control-Allow-Headers响应头来指定允许的请求头字段。 4. 可以通过设置Access-Control-Expose-Headers响应头来指定允许客户端访问的响应头字段。 5. 在客户端的XMLHttpRequest请求中需要设置withCredentials属性为true,以便允许携带身份凭证。 使用CORS可以灵活地控制跨域资源的访问权限,提高了安全性,并且不需要使用代理或JSONP等其他方法来实现跨域请求。但是需要注意的是,CORS只能解决部分跨域问题,不支持跨域文件上传和跨域流媒体传输等。 ### 回答3: 跨域请求是指在浏览器端,当网页的请求向不同域名、不同端口号或不同协议的服务器发起时,会被浏览器拦截,这是为了保护用户的安全。为了解决跨域问题,我们可以使用CORS(Cross-Origin Resource Sharing)。 CORS是一种通过在服务器端设置响应头来允许跨域请求的机制。具体方法如下: 1. 在服务端设置响应头:在服务器端的API接口中设置`Access-Control-Allow-Origin`响应头,允许指定的域名来访问该接口。例如,设置为`Access-Control-Allow-Origin: http://example.com`,表示只允许`http://example.com`域名来访问该接口。 2. 处理预请求:对于带有特殊请求方法(例如DELETE、PUT等)或自定义头部的请求,浏览器会首先发起一个OPTIONS预请求,来确认服务器是否接受该请求。在服务器端的API接口中,需要对OPTIONS请求进行特殊处理,设置相关的响应头,例如`Access-Control-Allow-Methods`(允许的方法)和`Access-Control-Allow-Headers`(允许的头部)。 3. 处理跨域携带凭证请求:对于需要在跨域请求中携带用户凭证(如cookie、authorization等)的情况,需要在服务器端的API接口中设置`Access-Control-Allow-Credentials: true`,表示允许跨域携带凭证。 4. 处理非简单请求:当请求方法为GET、POST、HEAD,并且没有自定义头部时,浏览器会发起简单请求,对于这种请求,服务器不需要额外设置响应头。 综上所述,使用CORS解决跨域问题的具体方法包括在服务器端设置`Access-Control-Allow-Origin`响应头,处理OPTIONS预请求,设置`Access-Control-Allow-Methods`和`Access-Control-Allow-Headers`来处理特殊请求,以及设置`Access-Control-Allow-Credentials`来处理跨域携带凭证请求。通过这些设置,可以实现跨域请求的安全和可控访问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值