1

COOKIE跨域获取问题

最近开发项目时,需要用到后端设置session,用户请求时,更具session设置给前端的cookie获取session的值,由于项目采用的是前端后端分离(前后端不在一个域上),故出现了如题所示问题:

功能介绍

  1. 用户在登陆时后端返回验证码图片,同时生成session,存储验证码的值,
  2. 用户的登陆时提交验证码的值,如果相同通过,不相同重新获取验证码

image

代码

// 获取验证码
  getCaptcha() {
    const { ctx } = this;
    const captcha = svgCaptcha.createMathExpr({
      inverse: false, // 翻转颜色
      fontSize: 50, // 字体大小
      noise: 1, // 噪声线条数
      width: 110, // 宽度
      height: 38, // 高度
      color: true, // 验证码的字符是否有颜色,默认没有,如果设定了背景,则默认有
    });
    ctx.session.maxAge = 1000 * 60; // 1分钟
    ctx.session.renew = false; // 设置在连续访问的时候不刷新剩余时间
    ctx.session.verifyCode = captcha.text; // 设置session
    this.success({
      code: captcha.data,
    });
  }

 // login
  async login() {
    const { ctx } = this;
    const { account, password, code } = ctx.request.body;
    const verifyCode = ctx.session.verifyCode;
    console.log(verifyCode);

    if (code !== verifyCode) {
      this.error('验证码错误', 444);
      return;
    }
    ...
  }

问题来了

一切访问正常,但是

  1. 用户登录时,后台取不到session,值为undefined
  2. 前端cookie里也无相应的值

解决

经过查阅,原因是cookie跨域,不能访问的原因,需要对代码进行相关设置:

参考: https://blog.csdn.net/weixin_...

前端(vue axios):

// 进行一些全局配置
axios.defaults.baseURL = 'http://127.0.0.1:7001'; //egg后台的地址
axios.defaults.timeout = 5000;
axios.defaults.withCredentials = true; // 让axios发送请求的时候带上cookie

设置后,访问如下:(这种情况下,还需要后端设置)

image

后端(用的是阿里的eggjs)

<span>注意:下面有origin的多种设置方式,特别是多个跨域,值得收藏哦</span>

config.cors = {
    // origin: '*',
    // origin: 'http://127.0.0.1:9384',
    origin(ctx) {
      // return "*"; // 允许来自所有域名请求
      // return ctx.header.origin;// 当*无法使用时,使用这句,同样允许所有跨域
      // return 'http://localhost:8080'; //单个跨域请求
      // 允许多个跨域
      const allowCors = [
        'http://localhost:9384',
        'http://127.0.0.1:9384',
        'http://172.16.92.62:9384',
      ];
      return allowCors.indexOf(ctx.header.origin) > -1 ? ctx.header.origin : '';
    },
    credentials: true, // 前台可以携带cookies 无此选项的话,还是上面的跨域
    allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
  };

设置后

image

可以正常获取到后台设置的cookie了(session会自动向前端设置一个cookei)

至此基本登陆可以正常进行了

但是

如果你用的是google浏览器,或者内核是chrome的浏览器,如果版本高于80

后台获取session,还是undefined

原因

image

上图可以看到,这种cookie没有成功

Chrome 51开始,浏览器的Cookie新增加了一个SameSite属性,用来防止CSRF攻击和用户追踪。
该设置当前默认是关闭的,但在Chrome 80之后,该功能默认已开启

参考 https://www.ruanyifeng.com/bl...

解决方法:

用户:

  1. 打开Chrome设置,将chrome://flags/#same-site-by-default-cookies禁用,然后重启浏览器。

image

  1. 使用低版本浏览器(chrome 小于80版本)

开发者:

  1. 方案1. 将SameSite属性值改为None, 同时 将secure属性设置为true。且需要将后端服务域名必须使用https协议访问。
  2. 由于设置SameSite = None,有SCRF风险,所以,最佳方案是用token代替Cookie方式作验证。

本例中的解决方案推荐使用Redis解决


wujh
9 声望1 粉丝