本篇文章主要介绍了微信小程序模拟 cookie的实现,内容挺不错的,现在分享给大家,也给大家做个参考。
开发背景
现有系统已经有一套完整的接口,用户状态、验证都是基于 cookie 的。
部分业务要上小程序版本,众所周知,微信小程序不支持 cookie 的。要上线的业务,最好的方式还是基于现有这套接口做,改动不大,也最快。
模拟 cookie
通过浏览器的开发工具,Network 栏查看请求,浏览器中的 cookie 会携带在每个 http 的 Request Headers 里面,用 Cookie 作为键名。
那么,在微信官方请求方式 wx.request 中,我们设置 header,添加一个 Cookie 应该可以得以模拟。
问题又来了,怎么获取到服务器返回的 cookie 呢。
通过登录接口(登录的时候,服务器端会植入 cookie 作为 session),查看 http 返回头。
wx.request({ url: #39;/api/login #39;, success: (data) = { if(data.statusCode === 200) { console.log(data); // data 中应该会有 Set-Cookie 或 set-cookie 的字样,嗯,那就是服务器种下的 cookie })
拿到 cookie 存入本地中,下次请求数据的时候直接塞进去,完美。
格式化 cookie
原本以为 cookie 只需要一进一出就可以完美模拟,实际操作才发现,携带上去的 cookie 服务器无法识别。
服务器返回的 cookie 中,会携带上很多储存用的字段,例如 path=/;
// 服务器放回的 cookie let cookie = #39;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 #39;; // 模拟的是需要的格式样式 let virtualCookie = #39;userKey=1234567890; userName=111111; userId=111; #39;;
妈耶~要怎么过滤呢。
简单粗糙的写了一个过滤方案。
// cookie 的本地存储位置 const COOKIE_KEY = #39;__cookie_key__ #39;; * 格式化用户需要的 cookie const normalizeUserCookie = (cookies = #39; #39;) = { let __cookies = []; (cookies.match(/([\w\-.]*)=([^\s=]+);/g) || []).forEach((str) = { if (str !== #39;Path=/; #39; str.indexOf( #39;csrfToken= #39;) !== 0) { __cookies.push(str); wx.setStorageSync(COOKIE_KEY, __cookies.join( #39; #39;)); };
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 #39;wepy #39;; export const HTTP_HOST = #39;http://127.0.0.1:3000 #39;; export const HTTP_HOST_API = `${HTTP_HOST}/api/wxmp`; // cookie 的本地存储位置 const COOKIE_KEY = #39;__cookie_key__ #39;; // csrfToken 的本地存储位置 const CSRF_TOKEN_KEY = #39;__csrf_token__ #39;; * 清除用户Cookie export const cleanUserCookie = () = { wx.setStorageSync(COOKIE_KEY, #39; #39;); * 格式化用户需要的 cookie * @param {String} cookies export const normalizeUserCookie = (cookies = #39; #39;) = { let __cookies = []; (cookies.match(/([\w\-.]*)=([^\s=]+);/g) || []).forEach((str) = { if (str !== #39;path=/; #39; str.indexOf( #39;csrfToken= #39;) !== 0) { __cookies.push(str); wx.setStorageSync(COOKIE_KEY, __cookies); * 格式化 token const normalizeCsrfToken = () = { let __value = wx.getStorageSync(CSRF_TOKEN_KEY) || #39; #39;; let __inputs = __value.match(/csrfToken=[\S]*/) || []; let __key = __inputs[0]; // csrfToken=1212132323; if (!!!__key) { return #39; #39;; // 脱水 return __key.replace(/;$/, #39; #39;).replace(/^csrfToken=/, #39; #39;); * 保存 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( #39;x-csrf-token #39;: csrf, Cookie: Cookies.join( #39; #39;) opt.header || {} opt.success = (data) = { seveCsrfTokenCookie(data.header[ #39;set-cookie #39;]); // 统一操作 if (data.statusCode == 200) { if (url === #39;/login #39;) { normalizeUserCookie(data.header[ #39;set-cookie #39;]); resolve(data.data); } else { reject( #39;未知错误,请重试一次 #39;); opt.fail = (err) = { reject(err); opt.url = `${HTTP_HOST_API}${opt.url}`; wepy.request(opt); };
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
微信小程序 Page()函数的介绍
微信小程序中wx:for和wx:for-item的用法
以上就是微信小程序模拟cookie的实现的详细内容,更多请关注php中文网其它相关文章!
微信app下载
微信是一款手机通信软件,支持通过手机网络发送语音短信、视频、图片和文字。微信可以单聊及群聊,还能根据地理位置找到附近的人,带给大家全新的移动沟通体验,有需要的小伙伴快来保存下载体验吧!