Node框架KOA2学习过程中遇见的跨域设置Cookie失效问题原因以及解决方案

4 篇文章 0 订阅

问题出现场景:在做登录功能时,想把用户的信息通过Set-cookie在客户端设置cookie信息。

  1. 服务端通过cors中间件实现接口跨域访问、koa-session-minimal实现cookie的设置。代码实现如下:
  const session = require('koa-session-minimal')
  const cors = require('@koa/cors');

  // app.js
  const app = new Koa()
  app.use(cors())

  // 存放sessionId的cookie配置, 相关的一些字段配置说明可以查看http协议。
  let cookie = {
    maxAge: 2 * 60 * 1000, // cookie有效时长
    expires: new Date('2022-08-26'),  // cookie失效时间
    path: '/', // 写cookie所在的路径
    domain: 'localhost', // 写cookie所在的域名
    httpOnly: false, // 是否只用于http请求中获取
    overwrite: false,  // 是否允许重写
    // secure: '',
    sameSite: 'strict',
    // signed: '',
  }

  // 使用session中间件
  app.use(session({
    key: 'SESSION_ID',
    cookie: cookie
  }))
  1. 登陆接口相关代码:
  // login接口
  // ...
  if (!err) {
    ctx.session = {
      user_id: adminId,
      count: 0
    }
    ctx.response.status = 200;
    // ...
  }
  // ...
  1. 一切进展顺利,接口响应成功,响应头也有我们设置的cookie字段。但是事情的背后往往没有这么简单,当我去看Application中的Cookie信息时,发现怎么都找不到我想要的SESSION_ID字段,百思不得姐。
    响应头
    响应头

遇见问题我们该做出些什么工作呢?

表情包
。。。

开个小玩笑,遇见问题我们当然得去分析问题的缘由,从问题的根本着手。

  1. 通过查阅一些资料后,发现浏览器的同源策略是对跨域的cookie有做一些限制的。其中Access-Control-Allow-Credentials字段就控制着对跨域cookie的设置。
  • Access-Control-Allow-Credentials 响应头用于在请求要求包含 credentials(Request.credentials 的值为 include)时,告知浏览器是否可以将对请求的响应暴露给前端 JavaScript 代码。
    当请求的 credentials 模式为 include 时,浏览器仅在响应标头 Access-Control-Allow-Credentials 的值为 true 的情况下将响应暴露给前端的 JavaScript 代码。(这段文字是来自MDN文档)。我理解是只有开启后,浏览器在读取到响应头的Set-cookie字段时,才能将cookie字段设置于浏览器中。于是我根据cors使用文档做出了代码上的调整:
    const app = new Koa()
    const koaOptions = {
      origin: 'http://localhost:9529',
      credentials: true
    };
    app.use(cors(koaOptions))
  1. 于是本人胸有成竹的开启了新一遍的流程测试,想必这次是能成功的。经过了几S的流程测试之后,我得到了一个结果:失败是成功之母。显然我们这次又未在Application的cookie中找到我们想要的SESSION_ID字段,我再次沉浸式的翻阅了MDN的cookie相关文档。

  2. 发现文档中其实是有写到:Access-Control-Allow-Credentials 标头需要与 XMLHttpRequest.withCredentials 或 Fetch API 的 Request() 构造函数中的 credentials 选项结合使用。Credentials 必须在前后端都被配置(即 Access-Control-Allow-Credentials header 和 XHR 或 Fetch request 中都要配置)才能使带 credentials 的 CORS 请求成功。

  • XMLHttpRequest.withCredentials 属性是一个布尔类型,它指示了是否该使用类似 Cookies、Authorization Headers (头部授权) 或者 TLS 客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用 withCredentials 属性是无效的。
    此外,这个指示也会被用做响应中 Cookies 被忽视的标示。默认值是 false。
    如果在发送来自其他域的 XMLHttpRequest 请求之前,未设置withCredentials 为 true,那么就不能为它自己的域设置 Cookie 值。而通过设置 withCredentials 为 true 获得的第三方 Cookies,将会依旧享受同源策略,因此不能被通过document.cookie或者从头部相应请求的脚本等访问。(这段文字是来自MDN文档)。
  1. 根据以上信息,我调整了前端项目封装的request模块代码,将withCredentiaols设置成了true:
    const service = axios.create({
      baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
      withCredentials: true, // send cookies when cross-domain requests
      timeout: 5000 // request timeout
    })
  1. 再一次的进行我们的流程测试,果然功夫不负有心人,终于是在Application中看到了心心念的SESSION_ID:
    在这里插入图片描述
    在这里插入图片描述

反思和结语

踏破铁鞋无觅处,得来全不费工夫。我们在遇见问题的时候,应该尽量从问题的本质出发寻找突破口,试着从另一个角度切入。其次就是对相关知识的掌握程度,我在这次的遇见问题和解决问题的过程中做出了反思,确实有寻找到突破口:浏览器的同源策略限制。但是对其相关的策略掌握不够深入,导致花费了比正常多几倍的时间去解决问题,经过这次的文档查阅,我对跨域设置cookie以及浏览器同源限制策略,有了更进一步的认知。最后我想说的是:不积跬步无以至千里。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值