前端怎么获取cookie的值_京东购物小程序cookie方案实践(附Demo)

一、前言

早期为了解决“会话保持”的需求,社区中出现了「cookie 方案」并最终成为 W3C 标准:当某个网站登录成功后,客户端(浏览器)收到一个 cookie 标识(文本)并保存下来,在后续请求中会自动带上这个字段,由此 Web 后台可以判断是否同一个用户,从而使“会话”得以延续。

微信小程序没有像浏览器一样内置实现了 cookie 方案,需要开发者自行模拟,而原先京东购物小程序及京喜小程序(现微信一级购物入口)是从微信及手 Q 购物入口 H5 中迁移迭代出来的,也就是说我们不仅要在小程序中模拟一套 cookie 方案,并且要保持和原业务对 cookie 处理逻辑的一致,为此我们将实现方向确定为“基于小程序开放能力,和浏览器保持一致”。

微信小程序开放了 数据缓存 Storage[1] 和 网络 Network[2] 这两种能力,通过这两套 API,我们可以自行 DIY 一个 cookie 方案。

PS:本文所有代码及使用示例都可以 在这里[3] 找到,阅读本文时配合实践,效果更佳。

二、浏览器中的 cookie

为了保持后端对 cookie 的处理逻辑和原来的 H5 一致,小程序的实现需要往浏览器看齐。

所以模拟小程序的 cookie 前,先看看浏览器的 cookie 机制,主要有以下几个部分:

  • 本地存储:浏览器会在本地分配一块空间,存储 cookie
  • 请求携带:每次发起请求,都会从本地取出 cookie 并追加在请求头上
  • 响应设置:当响应头有 Set-Cookie 字段时,需要解析并更新
  • 过期时间:每个 cookie 字段有单独的过期时间,并且到期会自动清除
  • 读写操作:暴露 API 给前端 JS 调用,可进行增删改查操作
  • 作用域:路径 path、域名 domin
  • 编码:cookie 值,在网络传输需要 encode,建议存储也一样
  • 其它:HttpOnly、Secure、SameSite

在浏览器的 DevTools 中,可以看到当前站点下的 Cookie 明细:f8aea9f46351dcc96ac9ee28bfd72a3c.png

三、小程序中的 cookie 实现

方案设计

在小程序中模拟 Cookie,主要涉及五个部分:eb05acddab03828ddb93a996d8008894.png其中我们会重点关注 「Cookie 基础库」 的实现,另外也会给出「Request 基础库」的封装示例。

本地存储

小程序提供了 「数据缓存 Storage API」(可以理解为 Web 规范中的 LocalStorage),支持存储“原生类型、Date、及能够通过 JSON.stringify 序列化的对象”。

我们可以利用这些 API,在 Storage 中新开一个 cookies 字段进行存储:

// 存:
wx.setStorageSync('cookies', cookies)
// 取:
wx.getStorageSync('cookies')

其中 cookies 的「存储结构」如下:

// cookies =
{
cookie1: { // “最小 cookie 单元” ==> cookieItem
name: 'cookie1', // cookie 名
value: 'xxx', // cookie 值
expires: 'Fri, 17 Jan 2020 08:49:41 GMT' // 过期时间,使用 GMT(格林威治标准时间)格式
}
},

上面的 cookie1 便是一个“最小 cookie 单元 cookieItem”,包含了 3 个字段(name、value、expires),是本文中定义的「标准 cookie 格式」,也是 cookie 操作的基本单元。

打开【微信开发工具】的 Storage 选项卡,可以查看本地存储的情况:aa161ec5dbd803135d611611b12dc33a.png

读写操作

这部分主要作为“公共基础库“的角色,为外部业务提供增删改查 cookie 的 API。

1. 获取 cookie————getCookie()

步骤:从 Storage 中取出完整 cookies ==> 取出指定 name 的 cookie 项 ==> 校验有效期 ==> 返回值 value

实现如下:

function getCookie(name = '') {
let cookies = wx.getStorageSync('cookies') // try/catch 略过
let { value, expires } = cookies[name] || {}

return (name && expires && !isExpired(expires)) ? decodeURIComponent(cookieItem.value) : ''
}

2. 设置 cookie————setCookie()

步骤:从 Storage 中取出完整 cookies ==> 解析入参 ==> 覆盖更新 ==> 同步到本地 Storage

首先看下本 API 设计需求:

  • 设置单个/多个 cookie
  • 直接传值/传 cookieItem(Object)
  • 时间格式 maxAge/expires

调用示例如下:

setCookie({
cookie1: 12345,
cookie2: '12345'
})

setCookie({
cookie1: {
value: 12345,
maxAge: 3600 * 24 // 自定义有效期(这里示例是24小时)
},
cookie2: {
value: '12345',
expires: 'Wed, 21 Oct 2015 07:28:00 GMT' // 标准 GMT 格式
}
})

这里可对入参遍历,而 cookie 子项无论直接传值 value 还是传了详细 object,都尽量的获取 name/value/expires/maxAge,传给格式化函数转为标准的 cookieItem

function setCookie(cookiesParam) {
let oldCookies = wx.getStorageSync('cookies') // try/catch 略过
let newCookies = {} // 由 cookiesParam 转化为标准格式后的 cookies

for (let name in cookiesParam) {
if (isObject(cookiesParam[name])) { // 传入是 Object 格式
let { value, expires, maxAge } = cookiesParam[name]
// 转换为标准 cookie 格式(cookieItem)
newCookies[name] = getStandardCookieItem({ name, value, expires, maxAge })
} else {
newCookies[name] = getStandardCookieItem({ name, value: cookiesParam[name] })
}
}

// 同步到本地 Storage
saveCookiesToStorage(Object.assign({}, oldCookies, newCookies))
}

3. 删除 cookie————removeCookie()

步骤:从 Storage 中取出完整 cookies ==> 删除指定的 cookie 项 ==> 同步到本地 Storage

function removeCookie(cookieName) {
let cookies = wx.getStorageSync('cookies') // try/catch 略过

delete cookies[cookieName]

saveCookiesToStorage(Object.assign({}, cookies))
}

四、Cookie 在网络中的传递

本节主要简单实现设计图中的【Request 基础库】部分

d96330497b314b2272e2abe470f23276.png

如上图所示,Cookie 在网络中的传输主要有四个过程:

  • 客户端发起 HTTP 请求
  • 服务端响应,并在响应头加上 Set-Cookie,客户端接受并解析保存
  • 下一次客户端发起 HTTP 请求,在请求头加上 Cookie
  • 服务端识别出请求头的 Cookie,作出相应处理

以下是对一个请求的抓包示例:c30aec26cf4ae3ad4f270ad913841b36.png

在小程序中,请求发起有两种方式:HTTPWebSocket,这里以 HTTP 为例,先对请求 api 进行「封装」:

function requestPro({ url, data, header, method = 'GET' }) {
return new Promise((resolve, reject) => {
wx.request({
url,
data,
header: Object.assign({}, { 'Cookie': CookieLib.getCookiesStr() }, header), // 请求头————带上 Cookie
success (res) {
let { data : resData, header, statusCode } = res
let setCookieStr = header['Set-Cookie'] || header['set-cookie'] || ''

CookieLib.setCookieFromHeader(setCookieStr) // 响应头————解析 Set-Cookie
resolve(resData)
},
fail (err) {
reject(err)
}
})
})
}

如上代码所示,Cookie 在前端侧请求模块中的处理主要有 3 点:

1. 请求携带

步骤:(每次发请求前)从 Storage 中取出完整 cookies ==> 转化为 HTTP 规范的请求头 Cookie 格式 ==> 设置到 Request Header

上面代码中的 getCookiesStr() 直接取 cookies 拼接即可,返回示例:cookie1=xxx;cookie2=yyy

2. 响应设置

步骤:(每次收到响应后)解析 Response HeaderSet-Cookie 字段 ==> 转为标准 Cookie 格式 ==> setCookie()

这里处理 Set-Cookie 内容时,有几个点需要留意:- 最基本的格式:Set-Cookie: = - 可能同时包含多个 cookie 字段,以,分割(但需要排除时间值里的,) - 时间格式:Max-Age/Expires (不区分大小写)

具体实现可在文末 Demo 中找到。

3. 编码问题

「Cookie 值编码方式」是容易产生困惑的地方,目前看到的广泛做法都是使用「URL 编码」。

但笔者翻阅 RFC6265[4] 发现,原始规范中并没有对编码进行指定,比如在第四章 Server Requirements (服务端)中是这样描述:

To maximize compatibility with user agents, servers that wish to store arbitrary data in a cookie-value SHOULD encode that data, for example, using Base64 [RFC4648].

“为了最好的兼容效果,服务端应该对 cookie 值进行编码,例如使用 Base64。”

而在第五章 User Agent Requirements (客户端,也就是浏览器),则是“建议以第四章服务端的实现为准”。

总之规范并没有指定使用「URL 编码」,但基于该编码方案已经深入人心,也就顺其自然成了“默认选择”。那这里也不做例外,浏览器怎么做,咱们小程序也保持一致。

在浏览器中,推荐 cookie 值经过 encode 编码后保存下来,所以直接取到的也是 encode 后的值,所以追加在请求头 Cookie 字段,就不需要 decode 解码了,直接拼接即可(但基础库 API 的 get 操作最终需要进行 decode 解码)。

而对于响应头 Set-Cookie 的值,我们认为后端已经做了 encode 编码,所以前端不需要处理,直接存进 Storage 即可。

五、性能优化(高频读写)

前面实现中每次读写 cookie 都会调用小程序 Storage API(而且是同步的),小程序框架会读写到本地 Storage。对于高频场景,可以将 cookie 在内存中维护一份,读写都直接走「内存层」,有更新才同步到「Storage 层」。

1. 初始化

首先需要在内存中声明一个 _COOKIES(命名自行 diy),建议在 cookie 基础库中声明,便于统一维护。

2. 读

前面初始化时已经从 Storage 读取一次 cookies,后续 getCookie 就直接读内存的 _COOKIES 即可。

3. 写

写操作直接更新内存,间接更新 Storage。如果有高频写场景,可以考虑做个任务队列进行节流。

六、单元测试

微信官方在 2019 年 5 月推出了「小程序自动化 SDK」 miniprogram-automator,经过半年多的迭代,目前已基本稳定下来。

在购物小程序场景试用了一下,cookie 相关的用例很快就完成了,简直是开发者的福音:真香!!!

47fc2090ffbdac0e20cf8b8a95b14e39.png

实际项目中,对 cookie 的单元测试可以分为两类:

  • 小程序全局范围的 cookie 验证(比如初始化小程序后,有没有种下版本号、访问行为等关键 cookie)
  • cookie 基础库 API 验证(比如 get/set/remove 等各个 API 是否正常工作)

以验证 setCookie()API 为例:

it('API 验证:setCookie()', async () => {
await miniProgram.evaluate(() => {
wx.CookieLib.setCookie({ // 调用 API
cookie1: 12345,
})
})

let { cookies } = await miniProgram.callWxMethod('getStorageSync', 'cookies')
expect(cookies['cookie1'].value).toBe(12345) // 期望成功设置 cookie1为12345
})

这里为了方便测试用例调用基础库 API,在小程序启动前,把 Cookie 基础库(CookieLib)挂到了 wx 对象上,实现方式是使用 node 读写文件的 API 去【植入代码】:

fs.appendFileSync('./your_project/app.js', ''\n wx.CookieUtil = require(\'./lib/cookie.js\');\n'')

七、Cookie 安全

Cookie 安全是一个比较大的话题,这里只简单列出和小程序相关的几个点。

path、domin、HttpOnly、Secure、SameSite

小程序中已经做了一些安全措施,比如只能走 HTTPS、合法域名需要管理员到微信后台进行配置、Storage 只能由写入它的小程序中访问,等等。因此 path、domin、HttpOnly、Secure、SameSite 这些字段在小程序环境下的价值没有浏览器环境大,本例中没有使用(懒..),而实际业务场景可以按自身情况决定是否要使用。

白名单机制

1 前端维护(大小/数量)

通常浏览器保持的 Cookie 数据不超过 4k,部分浏览器限制同一站点最多 cookie 数为 20 个。

如果业务庞大的话,建议在 Cookie 基础库做一套「白名单」机制,在白名单内才可以写入,以此防止“非法写入”或“内容超大导致信息丢失”的问题。

2 后台维护(网关白名单)

同样的,建议从网关层面,建立一个“可信 cookie”白名单,自动过滤请求中的“非法 cookie”字段。

前端防篡改

小程序前端更多是防“误改”————即在操作 Cookie 过程中,发生了意料之外的修改。通常发生在 JS “引用拷贝”特性上,比如前面提到的内存维护一个 _Cookies,如果有一个 API getAllCookies() 直接将这份内存版 cookies 暴露出去,对象引用容易被连带修改。所以 cookie 基础库需要控制暴露 API 的能力范围,并对取值进行“深拷贝”。

Session

Session 机制将用户状态放在了服务端维护,具备更好的安全性,而且目前各种后端对于 session 的存储和同步都有很成熟的技术方案,有条件的业务应以 Session 为主做会话保持。

指纹上报

用户访问时生成设备指纹并上报(通常是登录/结算等环节),业务后台配合风控系统,遇到异常请求时下发验证环节。

八、完整小程序实现 Demo

代码片段:https://developers.weixin.qq.com/s/x4sFASmh7xdq

474a4314c94921a9d3489cae20604af5.png

九、小结

本文先解析了浏览器的 Cookie 机制 运作原理,然后使用「数据缓存」和「网络」能力,以 公共基础库 的形式,在小程序中实现了一套 Cookie 方案。希望对大家有所帮助。

十、相关链接

  • RFC6265(HTTP 状态管理机制规范)[5]
  • HTTP Cookies Explained[6]
  • 小程序数据缓存 Storage API[7]
  • 小程序网络 Network API[8]
  • 小程序自动化 SDK[9]
  • 小程序实现 Demo[10]

参考资料

[1]

数据缓存 Storage: https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorageSync.html

[2]

网络 Network: https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html

[3]

在这里: https://developers.weixin.qq.com/s/x4sFASmh7xdq

[4]

RFC6265: https://tools.ietf.org/html/rfc6265

[5]

RFC6265(HTTP 状态管理机制规范): https://tools.ietf.org/html/rfc6265

[6]

HTTP Cookies Explained: https://humanwhocodes.com/blog/2009/05/05/http-cookies-explained/

[7]

小程序数据缓存 Storage API: https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorageSync.html

[8]

小程序网络 Network API: https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html

[9]

小程序自动化 SDK: https://developers.weixin.qq.com/miniprogram/dev/devtools/auto/

[10]

小程序实现 Demo: https://developers.weixin.qq.com/s/x4sFASmh7xdq

f128b48ca584f90a0b070b3731afa5e4.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505191.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R 语言怎么保存工作目录到当前路径_【R语言基础】01.R语言软件环境搭建及常用操作...

一、R语言简介R语言是专业的统计分析软件,来自著名数据科学网站(http://www.kdnuggets.com/)发起的一个2019年统计分析和数据挖掘软件使用情况的调查结果:表明R语言是该领域近年来最受欢迎的软件之一。R语言的优势:(1)…

ssm java上传图片预览_ssm文件上传_上传图片

1、搭建好ssm框架2、导入文件上传所需依赖commons-fileuploadcommons-fileupload1.4commons-iocommons-io2.6commons-langcommons-lang2.63、springmvc的xml文件中配置文件所需的类4、jsp界面对应其次第二个文件上传对应的就是第二个div里面的内容4、form表单配置注意&#xff…

平台允许同时在线人数 显示_12万人同时在线,游戏未正式发售,国产“糖豆人”已诞生?...

《派对动物》目前在Steam平台上开启了试玩阶段,游戏离正式发行还有一段时间。这款游戏适合多人作战,正如它的名字一样《派对动物》。不过从游戏角色的形象设定上来看,有一些像学龄前儿童喜爱的动画片,因此并没有人给这部游戏太多的…

feign post 传递空值_听我讲完GET、POST原理,面试官给我倒了杯卡布奇诺

文章来源:听我讲完GET、POST原理,面试官给我倒了杯卡布奇诺原文作者:陈哈哈来源平台:CSDN我有一个老朋友,我们叫他熊猫。发际线及将触碰到后脑勺,大框金丝眼镜也掩盖不住那黝黑的眼圈,显得格外的…

java必知必会_Java构造器必知必会

在面向对象编程中,编程人员应该在意“资源”。比如String hello "hello";在代码中,我们很在意在内存中String类型的hello,它是有一个生命周期的。在它生命周期中,初始化(initialization)和清理(cleanup)是两…

post 请求 argument type mismatch_Flask-RESTful 请求解析

一、基本参数from flask.ext.restful import reqparseparser reqparse.RequestParser()parser.add_argument(rate, typeint, helpRate cannot be converted)parser.add_argument(name, typestr)args parser.parse_args()二、必需的参数parser.add_argument(name, typestr, re…

易语言单窗口单ip软件源码_梦幻西游怎样多开ip转金?十大攻略秘籍速来看

各位好!,我依然是小芝麻,近期几日总是有盆友在私聊我,“小芝麻看着你的转金专缉,那么多方式,能够 帮我建议一类,最安全可靠能用的吗?”“小芝麻,你的转金攻略大全&#x…

maven不配置环境变量可以使用吗_哪些土地可以不缴纳土地使用税?包括农村地吗?...

根据法律规定,县城以上城市进行土地开发时,需要征收土地使用税,对于公园、名胜、寺庙及文教、卫生、社会福利等单位使用的土地,城镇、街道、公共设施用地、铁路、机场、港区、车站、管理交通运输用地及水利工程,农、林…

小米答题题库_拼多多果园答题题库74(每日更新)

135编辑器拼多多答题题库七十四每周我们都会做一个总和的题库;希望大家持续关注!您的关注就是我们的动力!“成语之乡”指的是我国哪座城市?1.河北邯郸 2.安徽蚌埠答:河北邯郸邯郸位于河北省南部,是战国时期…

java 接口 print_Java-接口练习

编写2个接口:InterfaceA和InterfaceB;在接口InterfaceA中有个方法voidprintCapitalLetter();在接口InterfaceB中有个方法void printLowercaseLetter();然后写一个类Print实现接口InterfaceA和InterfaceB,要求printCapi…

filestorage 修改吧部分数据_数据库系统概论课后答案||第五版

关注公众号,更多资源分享回复关键词:数据库系统概论即可获取相应资源其他章节关注公众号获取第 1 章 绪论1 . 试述数据、 数据库、 数据库系统、 数据库管理系统的概念。答:( l ) 数据( Data ) : 描述事物的符号记录称…

directshow 旋转_宜昌中心加工机+A:B型号,高速旋转接头加工

杭州浙稳贺机械配件有限公司为您详细解读MrGAtc宜昌中心加工机A:B型号的相关知识与详情,但是,0.1-0.15 N/ mm范畴的密封唇载荷对新的密封是可承受的;关于80mm曲径的轴,那转换为25-40N范畴的总径向载荷。很多旋转接头弹性体唇形密封…

jsp是在html里面嵌入哪种代码?_奶茶店铺用哪种制冰机才合适?

像在这样炎炎的夏日,温度在直线飙升,茶饮市场最近可谓是异常火,店铺人流量一旦增多,还能保证每一杯饮品的质量吗?还能保证门店的制冰机产量能够跟上需求节奏吗?奶茶店铺用哪种制冰机才合适?今天…

redis哨兵主从不切换_《「面试突击」—Redis篇》-- Redis的主从复制?哨兵机制?...

Redis如何保证高并发,高可用?高并发:redis的单机吞吐量可以达到几万不是问题,如果想提高redis的读写能力,可以用redis的主从架构,redis天热支持一主多从的准备模式,单主负责写请求多从负责读请求…

run till exit from #0_华为认证hcip H13821 v2.0云服务考试真题每日一练(一)

1.微服务云应用平台(ServiceStage),可以完成以下哪些功能?(多选)A.创建应用依赖计算资源B.使用 AOS 模板自动化应用编排C.查看应用各项指标D.在线可视化升级应用E.容器应用需要自己在 Service Storage 上搭建容器管理平台,比如需自己搭建 kubernetes 管理 docker 容器应用Answ…

什么笔记本电脑好用_苹果笔记本好用吗?苹果笔记本怎么样?

阅读本文前,请您先点击上面的蓝色字体“科技论吖”,再点击“关注”,这样您就可以继续免费收到文章了。每天都有分享,完全是免费订阅,请放心关注!苹果笔记本好用吗苹果笔记本好用吗?用苹果电脑最大的好处就…

apple ii 模拟器 mac_苹果自研芯片Mac价格曝光

11月3日凌晨,苹果又在官网宣布了今年秋季的第三场新品发布会将在北京时间2020年11月11日凌晨2点举行,这次发布会预计会带来搭载苹果自研Apple Silicon芯片的Mac产品。彭博社的报道显示,这次的新品发布会将会推出三款产品,分别是13…

win10文件夹加密_(十六)小众但好用:免费开源免注册的同步盘加密工具 Cryptomator...

之前写过同步盘加密工具 boxcryptor,今天给大家推荐另一款开源免费多平台的同步盘加密工具 Cryptomator。节省时间,直接开始。Cryptomator 官方网站:点击这里首先简单对比一下 Cryptomator 和 boxcryptor。Cryptomator 加密原理和 boxcryptor…

simulink仿真及代码生成技术入门到精通_Simulink仿真零基础入门到精通实用教学教程 自学全套...

Simulink仿真零基础入门到精通实用教学教程 自学全套,以教程文字为主,毕业论文和报告均可以借鉴。Simulink是电气工程必学的模型仿真专业工具软件,非常的实用。小编在全网中搜索都没有找到非常系统的学习教程和教材,想学习却找不到…

plupload怎么设置属性_店铺收银系统怎么用?好收银系统能提升店铺效率

经营一家店铺,无论是小型便利店还是大型超市,都少不了使用收益系统,那么常用的店铺收银系统要怎么用呢?店铺收银系统怎么用一款好用的收银系统,是可以起到提升店铺首页效率的,现在信息时代,不少收银系统开…