前面作者写的 COOKIE 篇, SESSION 篇, 算是已经比较详细的说明了两者间的区别, 机制, 联系了. 阅读时间可能稍长, 因为作者本身作图也做了不短时间, 都是为了能形象的把 COOKIE 和 SESSION 的运行原理描述出来, 但花点时间去阅读理解他们是值得的. 因为这个技术点虽然小, 但涉及到前后端交互, 无论是做前端还是后台, 都需要懂. 不然, 只会遭同事鄙视...... 所以, 为了不被鄙视, 还是好好读多点书, 充实自己.
如果还未搞懂 COOKIE 和 SESSION 的, 建议去看看前面的两篇文章, 再来看本篇, 本篇主要重在实践, 而不会再细讲原理性的东西.
设置 COOKIE
使用原生 NODE 会让代码变得更复杂一些, 为了方便演示代码这里使用到 NODE.JS 的框架 Express, 反正我们主要是讲 COOKIE, 框架无影响.
- const express = require('express');
- var server = express();
- server.use('/cnblogs/wljqds', (req, res) => {
- // 给客户端返回一个 cookie
- res.cookie('user', 'wljqds', {
- path: '/cnblogs/wljqds',
- maxAge: 20*60*1000
- });
- res.send('ok');
- });
- server.listen(8080);
运行结果:(在浏览器中输入 localhost:8080/cnblogs/wljqds)
根据 cookie 篇中的说法, 这个时候在响应首部 (Response) 应该会有 Set-Cookie 字段(在第一篇中有写到)
path 对 COOKIE 访问的影响
domain 和 path 字段结合起来就能限制浏览器对 COOKIE 的访问, 在 domain 都是默认的情况下(一般而言都是根域名), 只有 path 起作用, 在 COOKIE 篇, 用博客园为例说明了, 在此我们可以用自己的代码说明, 在上述代码中我们设置 COOKIE 的 path 值为 path: '/cnblogs/wljqds', 其实只要理解一点下级目录可以用上级目录的 cookie, 反之不可则容易了, 为了说明这种情况, 相对上述代码添加一个上级目录路由以及一个下级目录.
- const express = require('express');
- var server = express();
- // 相对 path: '/cnblogs/wljqds'来说,/ 是上级目录
- server.use('/', (req, res) => {
- res.send('ok');
- });
- // 相对 path: '/cnblogs/wljqds'来说,/cnblogs/wljqds/article 是下级目录
- server.use('/cnblogs/wljqds/article', (req, res) => {
- res.send('ok');
- });
- server.listen(8080);
在运行代码前, 我有必要说明一点: 前面我们已经保存了一个 cookie 了, 这时候我们只是去查看 cookie, 验证 path 对 cookie 的限制.
首先, 是根路径是否能访问 cookie, 访问根路径 localhost:8080/
在 localhost:8080 根路径下, 没有任何的 cookie, 说明上级不能访问下级的 cookie.
另外一个在此由于篇幅问题不在演示, 读者们可以用代码自己尝试, 记住一点: cookie 对下级目录可以访问, 但上级不可以.
设置 COOKIE 签名
其实在 COOKIE 篇中, 有一个非常重要的概念没有谈及, 那就是 COOKIE 签名, 一些重要的信息保存在 COOKIE, 这时候是要 COOKIE 的. 在这里补充知识, 并且说明如何设置 COOKIE 签名.
首先 COOKIE 签名的作用是防止 COOKIE 被篡改!, 通过在服务端验证签名从而能做到防止 COOKIE 篡改.
函数签名这个概念, 需要从两个方面理解:
1. 服务端把一个带签名 COOKIE 发送到客户端: 服务端会生成一个秘钥, 再使用加密算法比如 HMAC-SHA256 算法对 COOKIE 数据和秘钥一起加密得到一个签名, 然后将这个签名加到 COOKIE 中, 再发送给客户端.
2. 服务端对客户端发送过来的 COOKIE 进行签名检验: 当客户端再次发起请求的时候会将这个已经签名的 COOKIE 一起发送到服务器中, 服务器中会把之前生成的秘钥跟 COOKIE 数据再次通过相同的算法进行加密, 得到一个签名, 再与发送过来的签名作对比, 如果签名不相等, 则证明 COOKIE 已经被篡改了!
通过上述的原理, 代码实现 COOKIE 签名
- const express = require('express');
- const cookieParse = require('cookie-parser');
- var server = express();
- // 添加一个秘钥, 通过秘钥生成签名与验证
- server.use(cookieParse('qvqonvpasvoqsgf'));
- server.use('/cnblogs/wljqds', (req, res) => {
- // 给客户端返回一个 cookie
- res.cookie('user', 'wljqds', {
- path: '/cnblogs/wljqds',
- maxAge: 20*60*1000,
- signed: true // 设置签名为 true
- });
- // 使用 signedCookies, 而不是 cookies. 因为是签名的 COOKIE
- console.log(req.cookies);
- res.send('ok');
- });
- server.listen(8080);
控制台中输出: { user: 'wljqds' }, 浏览器中查看 COOKIE,COOKIE 值已经是加了一串签名.
读取 COOKIE
读取 cookie 用到一个中间件 cookie-parser, 非常简单, 需要注意一点就是. 如果是签名的 COOKIE, 必须使用 req.signedCookies.
- const express = require('express');
- const cookieParse = require('cookie-parser');
- var server = express();
- server.use(cookieParse());
- server.use('/cnblogs/wljqds', (req, res) => {
- // 给客户端返回一个 cookie
- res.cookie('user', 'wljqds', {
- path: '/cnblogs/wljqds',
- maxAge: 20*60*1000
- });
- // 输出请求中的 cookie
- console.log(req.cookies);
- // 删除一个 COOKIE
- res.clearCookies('user');
- res.send('ok');
- });
- server.listen(8080);
运行结果在控制台中输出:{ user: 'wljqds' }, 简单暴力.
session
session 的实践, 记忆犹新, 大一在学校上网站设计的课程, 我们老师问网站用什么来维持登录状态...... 班上的人居然没人能回答, 然后自己回宿舍去找相关资料, 为的就是下次跟老师讨论......
session 是依赖 cookie 的, 所以它同样需要中间件 cookie-parser, 另外还需要 cookie-session 中间件. session 配合项目使用就能明白他的强大. 在此只做一个 session 的简单小例子:
使用 session, 简单的记录访问次数
- const express = require('express');
- const cookieParser = require('cookie-parser');
- const cookieSession = require('cookie-session');
- var server = express();
- server.use(cookieParser('hnyetfsdnyth'));
- // 设置 session 相关信息
- server.use(cookieSession({
- // keys 是 session 的秘钥, 越多越好, 循环使用 keys 进行加密
- keys: ['aaa', 'bbb', 'ccc'],
- // session 的名字
- name: 'sessID',
- // session 的 ID, 不设置默认是关闭浏览器就过期
- maxAge: 20*60*1000
- }));
- server.get('/', (req, res) => {
- //
- if(req.session['count'] == null) {
- // 设置 COOKIE 中一个 count 字段
- req.session['count'] = 1;
- } else {
- req.session['count']++;
- }
- // 读取请求中的 session
- console.log(req.session['count']);
- res.send('ok');
- })
- server.listen(8080);
每进行一次页面刷新, 则相当于一次访问, 输出台:
总结:
首先先说自己的写作感受, 作者本人是第一次写文章, 也不知道自己能表达清楚或者错误理解, 后面会继续写自己所实践过的技术.
然后, COOKIE 和 SESSION 的方方面面都已经写完了, 不明白的可以讨论, 作者花了挺多时间在作图上, 不明白原理的话, 图文结合多想几次, 直到明白, 这种技术点一定要半桶水, 不然只会害了自己, 坑了同事.
再说, 这三篇文章其实涉及到的不止 COOKIE 和 SESSION, 前后端的交互作者都交待的挺清楚的, 读者们能从我的文章中得到新的知识就 OK, 写文章的乐趣就在于分享.
下次见.
如果您觉得阅读本文对您有帮助, 请点一下 "推荐" 按钮, 您的 "推荐" 将是我最大的写作动力!
来源: https://www.cnblogs.com/wljqds/p/node_cookie_session.html