遇到验证码后台session中不能使用的问题,那是因为跨域导致cookie不能成功写入和携带,解决问题的办法

跨域set-cookie无效的解决方案

上次在项目中做一个手机验证码功能时遇到后端set-cookie无法成功的问题,相信很多人都会遇到,今天分享出来,算是做个记录,也给有需要的小伙伴一个参考,下面先说一下场景

手机验证码实现步骤
用户输入手机号并点击发送验证码按钮

此时是向后端服务器发起高请求,传递手机号码
后端接收到手机号码后通过短信服务商的接口发送短信到手机号

由于安全性问题,一般服务商的接口都是由后端发起请求,那验证码是怎么来的呢?当然是我们自己后端生成的(一般是生产一个4位或6位随机数字号码),短信接口只负责发送
用户收到验证码后,在表单中输入并发送验证
后端收到验证码与第2步生成的进行校验,一致则通过,否则不通过
问题来了,我们都知道http请求是无状态的,即每个请求都是独立的,两个请求间没有任何联系,但上面的步骤中,用户发起了两次请求(第1步和第3步),后端怎么知道是同一个人呢?万一当时有10个人同时获取验证码,且都执行完所有步骤,怎么实现各自第1和第3步的对应关系进而进行第4步校验?于是我们引入session

什么是session
session是保存的服务器的一个数据存储机制,一般用于存储用户状态数据,你可以理解为客户端的cookie,因为它们很像,同样是有key/value和有效时间,只是一个在服务端,一个在客户端。这跟本文有什么关系呢?肯定有关系,关系大了去了,不然我写干嘛(自嗨中~~~)

咳~咳。。回归正题,刚刚说了http是无状态的,而我们现在又要把第1步和第3步关联起来,怎么关联呢?session+cookie出马,具体原理如下

第一次接到请求,后关会生成一个sessionid来标识当前会话(我使用express-session来实现),并通过set-cookie响应头在客户端生一个cookie,大概长这样,

connect.sid=s%3Au9xG34DBU1vOVbIpCax0neMxL_Uc1fIC.4ndNJL5G%2B41DtUSLbQ%2BW75Z9wduOAON4lfu2JGTDe5
由于cookie会自动发送给服务器,所以当前用户后面的所有请求都会携带这个sessionid给服务器,服务器通过这个sessionid来标识是否为同一个用户,问题就迎刃而解了…
手机验证码功能具体实现步骤
前端:

用户输入手机号,点击获取验证码
发送请求到后端,
后端:

后端生成随机验证码,保存在session,并给前端响应connect.sid(express-session会Set-Cookie响应头)
并通过手机接口发送给用户手机号(需要后端配置手机短信接口,一般需要购买,这里不做额外说明)
前端:

浏览器接收到Set-Cookie响应头后,自动把sessionid写入浏览器cookie
用户接收到手机验证码并填写到对应输入框
用户点击按钮发送验证码到后端进行校验(sessionid随cookie自动发送到后端)
后端:

后端拿到验证码,并与第3步保存在session的随机验证码进行比较,一致则响应成功,否则响应失败
通过以上步骤,正常情况下你已经能实现手机验证码功能了,可我偏偏遇到了非正常情况,这也是我今天这篇文章的意义,由于开发阶段为前后端分离,请求是产生了跨域,明明已经正确响应了Set-Cookie,允许了CORS跨域,但浏览器的cookie中就是看不到connect.sid的身影,关键浏览器还不报错。

于是各种千里寻她千百度,最后发现默认情况下,标准的跨域请求是不会发送cookie等用户认证凭据的,同样,后端通过Set-Cookie在跨域时默认是被浏览器忽略的,解决的方案是两步:

后端设置"Access-Control-Allow-Credentials":true响应头

PS: 设置该响应头后,Access-Control-Allow-Origin的值不能设置为 *,必须设置为具体域名
前端发起请求时设置 withCredentials:true 请求头

// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open(‘get’,url,true);
xhr.withCredentials = true;
xhr.send()

// axios
axios.get(url,{

withCredentials:true
})

// fetch
fetch(url,{

credentials: ‘include’
})

搞定,收工,希望对你有帮助

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值