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

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

手机验证码实现步骤

  1. 用户输入手机号并点击发送验证码按钮express

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

    因为安全性问题,通常服务商的接口都是由后端发起请求,那验证码是怎么来的呢?固然是咱们本身后端生成的(通常是生产一个4位或6位随机数字号码),短信接口只负责发送
  3. 用户收到验证码后,在表单中输入并发送验证
  4. 后端收到验证码与第2步生成的进行校验,一致则经过,不然不经过

问题来了,咱们都知道http请求是无状态的,即每一个请求都是独立的,两个请求间没有任何联系,但上面的步骤中,用户发起了两次请求(第1步和第3步),后端怎么知道是同一我的呢?万一当时有10我的同时获取验证码,且都执行完全部步骤,怎么实现各自第1和第3步的对应关系进而进行第4步校验?因而咱们引入session跨域

什么是session

session是保存的服务器的一个数据存储机制,通常用于存储用户状态数据,你能够理解为客户端的cookie,由于它们很像,一样是有key/value和有效时间,只是一个在服务端,一个在客户端。这跟本文有什么关系呢?确定有关系,关系大了去了,否则我写干吗(自嗨中~~~)浏览器

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

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

    connect.sid=s%3Au9xG34DBU1vOVbIpCax0neMxL_Uc1fIC.4ndNJL5G%2B41DtUSLbQ%2BW75Z9wduOAON4lfu2JGTDe5
  2. 因为cookie会自动发送给服务器,因此当前用户后面的全部请求都会携带这个sessionid给服务器,服务器经过这个sessionid来标识是否为同一个用户,问题就迎刃而解了...

手机验证码功能具体实现步骤

  1. 前端:cookie

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

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

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

    1. 后端拿到验证码,并与第3步保存在session的随机验证码进行比较,一致则响应成功,不然响应失败

经过以上步骤,正常状况下你已经能实现手机验证码功能了,可我恰恰遇到了非正常状况,这也是我今天这篇文章的意义,因为开发阶段为先后端分享,请求是产生了跨域,明明已经正确响应了Set-Cookie,容许了CORS跨域,但浏览器的cookie中就是看不到connect.sid的身影,关键浏览器还不报错。

因而各类千里寻她千百度,最后发现Set-Cookie在跨域时默认是被浏览器忽略的,解决的方案是两步:

  1. 后端设置"Access-Control-Allow-Credentials":true响应头
  2. 前端发起请求时设置 withCredentials:true 请求头

搞定,收工,但愿对你有帮助

相关文章
相关标签/搜索