当前位置:微信小程序开发 > 小程序资讯 > 小程序开发教程 > 微信小程序模拟cookie的实现

微信小程序模拟cookie的实现

2018-08-17 11:53 来源: 霸界科技

摘要:大部分的微信小程序不支持cookie,那么微信小程序模拟cookie的实现要如何开发,下面为大家带来微信小程序模拟cookie的实现过程。...

期权保本理财
  大部分的微信小程序不支持cookie,那么微信小程序模拟cookie的实现要如何开发,下面为大家带来微信小程序模拟cookie的实现过程。
 
微信小程序模拟cookie的实现
 
  开发背景
 
  现有系统已经有一套完整的接口,用户状态、验证都是基于 cookie 的。
 
  部分业务要上小程序版本,众所周知,微信小程序不支持 cookie 的。要上线的业务,最好的方式还是基于现有这套接口做,改动不大,也最快。
 
  模拟 cookie
 
  通过浏览器的开发工具,Network 栏查看请求,浏览器中的 cookie 会携带在每个 http 的 Request Headers 里面,用 Cookie 作为键名。
 
  那么,在微信官方请求方式 wx.request 中,我们设置 header,添加一个 Cookie 应该可以得以模拟。
 
  问题又来了,怎么获取到服务器返回的 cookie 呢。
 
  通过登录接口(登录的时候,服务器端会植入 cookie 作为 session),查看 http 返回头。
 
  wx.request({
 
  url: '/api/login',
 
  success: (data) => {
 
  if(data.statusCode === 200) {
 
  console.log(data);
 
  // data 中应该会有 Set-Cookie 或 set-cookie 的字样,嗯,那就是服务器种下的 cookie
 
  }
 
  }
 
  })拿到 cookie 存入本地中,下次请求数据的时候直接塞进去,完美。
 
  格式化 cookie
 
  原本以为 cookie 只需要一进一出就可以完美模拟,实际操作才发现,携带上去的 cookie 服务器无法识别。
 
  服务器返回的 cookie 中,会携带上很多储存用的字段,例如 path=/;
 
  // 服务器放回的 cookie
 
  let cookie = 'userKey=1234567890; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT; HttpOnly,userId=111; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT,nickName=; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT,userName=111111; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT,imgUrl=; Path=/; Expires=Thu, 21 Jun 2018 13:15:08 GMT';
 
  // 模拟的是需要的格式样式
 
  let virtualCookie = 'userKey=1234567890; userName=111111; userId=111;';妈耶~要怎么过滤呢。
 
  简单粗糙的写了一个过滤方案。
 
  // cookie 的本地存储位置
 
  const COOKIE_KEY = '__cookie_key__';
 
  /**
 
  * 格式化用户需要的 cookie
 
  */
 
  const normalizeUserCookie = (cookies = '') => {
 
  let __cookies = [];
 
  (cookies.match(/([\w\-.]*)=([^\s=]+);/g) || []).forEach((str) => {
 
  if (str !== 'Path=/;' && str.indexOf('csrfToken=') !== 0) {
 
  __cookies.push(str);
 
  }
 
  });
 
  wx.setStorageSync(COOKIE_KEY, __cookies.join(' '));
 
  };csrfToken 是接下来配合 Egg.js 用的,Path=/; 在某些应用下会是 path=/;
 
  normalizeUserCookie 主要是过滤了 xx=xxx; 这样的数据,然后排除 path=/; 这样无意义的数据。
 
  在登录接口的时候,存上 cookie,在接下来的请求中带上,那么,应该、没错、可能、可以模拟了。
 
  配合 Egg.js
 
  Egg 内置的 egg-security 插件默认对所有『非安全』的方法,例如 POST,PUT,DELETE 都进行 CSRF 校验。
 
  Egg.js 虽然可以在配置中关闭 CSRF,但是,如果一定要使用呢?
 
  首先,要弄明白一件事,csrfToken 怎么来的。
 
  经过多次验证得知,当 http 请求时,在约定位置没有携带上 csrfToken 值,此次请求会在返回的 cookie 中携带上一个新的 csrfToken;当本次请求已携带上值,就不会产生成 csrfToken。当约定位置带上的 csrfToken 与 cookie 里面的 csrfToken 一致时,通过验证。
 
  接上面的 格式化用户需要的 cookie 操作,先抛开 csrfToken 单独处理用户状态等。
 
  在每次请求结束后,试着单独拿 cookie 中可能存在的 csrfToken,有值就缓存,没值跳过用旧值。
 
  封装一个 Ajax
 
  本次小程序是基于 wepy 的,所以使用了优化后的 wepy.request;
 
  基于 Egg.js 的版本。
 
  可能与实际开发有点出入,适当修改。
 
  import wepy from 'wepy';
 
  export const HTTP_HOST = 'http://127.0.0.1:3000';
 
  export const HTTP_HOST_API = `${HTTP_HOST}/api/wxmp`;
 
  // cookie 的本地存储位置
 
  const COOKIE_KEY = '__cookie_key__';
 
  // csrfToken 的本地存储位置
 
  const CSRF_TOKEN_KEY = '__csrf_token__';
 
  /**
 
  * 清除用户Cookie
 
  */
 
  export const cleanUserCookie = () => {
 
  wx.setStorageSync(COOKIE_KEY, '');
 
  }
 
  /**
 
  * 格式化用户需要的 cookie
 
  * @param {String} cookies
 
  */
 
  export const normalizeUserCookie = (cookies = '') => {
 
  let __cookies = [];
 
  (cookies.match(/([\w\-.]*)=([^\s=]+);/g) || []).forEach((str) => {
 
  if (str !== 'path=/;' && str.indexOf('csrfToken=') !== 0) {
 
  __cookies.push(str);
 
  }
 
  });
 
  wx.setStorageSync(COOKIE_KEY, __cookies);
 
  };
 
  /**
 
  * 格式化 token
 
  */
 
  const normalizeCsrfToken = () => {
 
  let __value = wx.getStorageSync(CSRF_TOKEN_KEY) || '';
 
  let __inputs = __value.match(/csrfToken=[\S]*/) || [];
 
  let __key = __inputs[0]; // csrfToken=1212132323;
 
  if (!!!__key) {
 
  return '';
 
  }
 
  // 脱水
 
  return __key.replace(/;$/, '').replace(/^csrfToken=/, '');
 
  };
 
  /**
 
  * 保存 csrf 的cookie
 
  * 不一定每次请求都会更新 cookie
 
  * @param {String} cookie
 
  */
 
  const seveCsrfTokenCookie = (cookie) => {
 
  if (cookie) {
 
  wx.setStorageSync(CSRF_TOKEN_KEY, cookie);
 
  }
 
  };
 
  /**
 
  * 请求数据
 
  * @param {Object} opt
 
  */
 
  export const doAjax = (opt) => {
 
  return new Promise((resolve, reject) => {
 
  let Cookies = wx.getStorageSync(COOKIE_KEY) || [];
 
  let csrf = normalizeCsrfToken();
 
  let url = opt.url;
 
  // 整理 Cookie
 
  Cookies.push(`csrfToken=${csrf};`);
 
  // 设置请求头部
 
  opt.header = Object.assign(
 
  {
 
  'x-csrf-token': csrf,
 
  Cookie: Cookies.join(' ')
 
  },
 
  opt.header || {}
 
  );
 
  opt.success = (data) => {
 
  seveCsrfTokenCookie(data.header['set-cookie']);
 
  // 统一操作
 
  if (data.statusCode == 200) {
 
  if (url === '/login') {
 
  normalizeUserCookie(data.header['set-cookie']);
 
  }
 
  resolve(data.data);
 
  } else {
 
  reject('未知错误,请重试一次');
 
  }
 
  };
 
  opt.fail = (err) => {
 
  reject(err);
 
  };
 
  opt.url = `${HTTP_HOST_API}${opt.url}`;
 
  wepy.request(opt);
 
  });
 
  };
分享到:
最新评论

网友:

验证码: 点击我更换图片

联系我们

业务咨询:15918761088

招商咨询:15918761088(微信同号)

周一至周五 9:30-18:30

公司地址:广州市海珠区昌岗中路166号富盈国际大厦2505室

官方微信 官方微博

Copyright © 2018 www.keji168.com 广州霸界网络科技有限公司版权所有 粤ICP备18083764号-1

客服
套餐咨询,合作细节等
在线客服
电话咨询
159-1876-1088