前言 最近在参加面试找工作,陆陆续续的面了两三家。其中面试官问到了一个问题:如何解决跨域问题?我巴巴拉拉的一顿说,大概了说了四种方法,然后面试官紧接着又问:那跨域请求怎么携带cookie呢?(常规的面试套路,一般都会顺着你的回答往深了问)由于之前的项目都是同源的,不牵涉跨域访问,所以一时没有回答出来,后来研究了下,所以有了这篇文章 阅读本文,你将学到:1。学会withCredentials属性;2。学会axios配置withCredentials;3。学会设置AccessControlAllowOrigin属性;4。学会设置AccessControlAllowCredentials属性;5。学会解决跨域请求携带源站cookie的问题; 思路:使用express搭建第一个服务A(http:localhost:8000),运行在8000端口上;A服务托管index。html(用于在前端页面发送网络请求)文件;在A服务中写一个处理请求的路由,加载index。html页面时,种下cookie(这里种cookie为了在请求B服务时携带上);使用express搭建第二个服务B(http:localhost:8003),运行在8003端口上;在A服务托管的index。html页面去请求B服务,然后把cookie传过去; 先看下代码结构,相对比较的简单: A服务的代码:srcapp1。jsconstexpressrequire(express);constappexpress();index。html加载时会请求login接口设置cookieapp。get(login,(req,res){res。cookie(user,jay,{maxAge:2000000,httpOnly:true});res。json({code:0,message:登录成功});});此接口是检测cookie是否设置成功,如果设置成功的话,浏览器会自动携带上cookieapp。get(user,(req,res){req。headers。cookie:userjayconstuserreq。headers。cookie。split()〔1〕;res。json({code:0,user});});托管index。html页面这样的话在index。html中发起的请求,默认的源就是http:localhost:8000然后再去请求http:localhost:8003就会出现跨域了app。use(static,express。static(public));app。listen(8000,(){console。log(app1runningatport8000);}); index。html的代码:!DOCTYPEhtmlhtmllangenheadmetacharsetUTF8metahttpequivXUACompatiblecontentIEedgemetanameviewportcontentwidthdevicewidth,initialscale1。0titleDocumenttitleheadbodyh2thisisindex。htmlatport8000h2buttonidbutton发送同源请求buttonbuttonidcrossbutton发送跨域请求buttonbodyhtml B服务的代码:srcapp2。jsconstexpressrequire(express);constappexpress();定义一个接口,index。html页面请求这个接口就是跨域(因为端口不同)app。get(anotherService,(req,res){res。json({code:0,msg:这是8003端口返回的});});app。listen(8003,(){console。log(app2runningatport8003);});二、解决跨域携带cookie问题 首先我们先在A服务的index。html页面中得到一个cookie,运行A服务:npminstallexpressDnodesrcapp1。js 然后打开http:localhost:8000staticindex。html:没有问题的话,页面长这样: 这个时候F12打开控制台:可以看到发送了一个login请求,并且设置了cookie,也可以选择浏览器控制台的Application页签,选中cookie,可以看到cookie的信息: 然后我们点击页面上的发送同源请求按钮,可以看到发送了一个user请求,并且已经携带上了cookie: 接下来刺激的画面来了,我们点击发送跨域请求按钮,出现了跨域请求的报错: 重点:接下来开始解决跨域携带cookie问题:1。在前端请求的时候设置request对象的属性withCredentials为true; 什么是withCredentials? XMLHttpRequest。withCredentials属性是一个Boolean类型,它指示了是否该使用类似cookies,authorizationheaders(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(crosssiteAccessControl)请求。在同一个站点下使用withCredentials属性是无效的。 如果在发送来自其他域的XMLHttpRequest请求之前,未设置withCredentials为true,那么就不能为它自己的域设置cookie值。而通过设置withCredentials为true获得的第三方cookies,将会依旧享受同源策略,因此不能被通过document。cookie或者从头部相应请求的脚本等访问。修改跨域请求的代码crossButton。onclickfunction(){axios({withCredentials:true,新增method:get,url:http:localhost:8003anotherService,})。then((res){console。log(res);});}; 这个时候再去发送一个跨域请求,你会发现依旧报错,但是我们仔细看下报错,意思是需要设置header的AccessControlAllowOrigin属性: 2。在服务端设置AccessControlAllowOrigin 我们修改B(app2。js)服务的代码:在所有路由前增加,可以拦截所有请求app。all(,(req,res,next){res。header(AccessControlAllowOrigin,http:localhost:8000);next();}); 修改完之后再次发送一个跨域请求,你会发现,又报错了(接近崩溃),但是跟之前报的错不一样了,意思大概就是AccessControlAllowCredentials这个属性应该设置为true,但是显示得到的是个: 3。在服务端设置AccessControlAllowCredentials 再次修改B服务的代码(每次修改后需要重新运行):在所有路由前增加,可以拦截所有请求app。all(,(req,res,next){res。header(AccessControlAllowOrigin,http:localhost:8000);res。header(AccessControlAllowCredentials,true);新增next();}); 再发送一个跨域请求: 可以看到,这个跨域请求已经请求成功并且返回数据了!而且也携带了A服务的cookie,这个时候已经大功告成了。三、总结前端请求时在request对象中配置withCredentials:true;服务端在response的header中配置AccessControlAllowOrigin,http:xxx:{port};服务端在response的header中配置AccessControlAllowCredentials,true 如果看完这篇文章能够帮助到你,请点赞转发关注哦