状态管理:cookie和session
cookie
cookie的组成
cookie是浏览器中特有的一个概念,它就像浏览器的专属卡包,管理着各个网站的身份信息。
每个cookie就相当于是属于某个网站的一个卡片,它记录了下面的信息:
- key:键,比如「身份编号」
- value:值,比如袁小进的身份编号「14563D1550F2F76D69ECBF4DD54ABC95」,这有点像卡片的条形码,当然,它可以是任何信息
- domain:域,表达这个cookie是属于哪个网站的,比如
yuanjin.tech,表示这个cookie是属于yuanjin.tech这个网站的 - path:路径,表达这个cookie是属于该网站的哪个基路径的,就好比是同一家公司不同部门会颁发不同的出入证。比如
/news,表示这个cookie属于/news这个路径的。(后续详细解释) - secure:是否使用安全传输(后续详细解释)
- expire:过期时间,表示该cookie在什么时候过期
当浏览器向服务器发送一个请求的时候,它会瞄一眼自己的卡包,看看哪些卡片适合附带捎给服务器
如果一个cookie同时满足以下条件,则这个cookie会被附带到请求中
- cookie没有过期
- cookie中的域和这次请求的域是匹配的
- 比如cookie中的域是
yuanjin.tech,则可以匹配的请求域是yuanjin.tech、www.yuanjin.tech、blogs.yuanjin.tech等等 - 比如cookie中的域是
www.yuanjin.tech,则只能匹配www.yuanjin.tech这样的请求域 - cookie是不在乎端口的,只要域匹配即可
- 比如cookie中的域是
- cookie中的path和这次请求的path是匹配的
- 比如cookie中的path是
/news,则可以匹配的请求路径可以是/news、/news/detail、/news/a/b/c等等,但不能匹配/blogs - 如果cookie的path是
/,可以想象,能够匹配所有的路径
- 比如cookie中的path是
- 验证cookie的安全传输
- 如果cookie的secure属性是true,则请求协议必须是
https,否则不会发送该cookie - 如果cookie的secure属性是false,则请求协议可以是
http,也可以是https
- 如果cookie的secure属性是true,则请求协议必须是
如果一个cookie满足了上述的所有条件,则浏览器会把它自动加入到这次请求中
在前端index.js写入,为的是判断用户名是否正确,以及是否登陆上,避免了没有登陆的情况下就可以操作系统。
cookie 中间件
可以直接使用cookie中间件来帮助我们简化工作
安装
npm i cookie-parser
引入
let token = "";let cookies = document.cookie;//获取的到的cookie可能不止一个//每一个cookie是用;进行分割的//token=xxx;user=xxxx;id=xxxx;let cookieArr = cookies.split(";");//判断是否有名字叫tokenfor (let i = 0; i < cookieArr.length; i++) {let item = cookieArr[i];//每一个cookie都是一个键值对 xxx=xxxxxlet arr = item.split("=");if (arr[0] === "token") {token = arr[1];break;}}if (!token) {location.hash = "#/";return;} else {$.ajax({url: "/api/user/verify/woami",type: "GET",success: function (res) {if (res.code === 0) {$("#username").text(res.data.name);}else {location.hash = "#/";}}});$("#logout").on("click", function () {alert("确定退出吗?");$.ajax({url: "/api/user/verify/loginOut",type: "GET",success: function (res) {if (res.code === 0) {location.hash = "#/";}}})});}
在user中写入接受前端传送过来的数据并进行匹配
需要插入中间件拦截,
const {pathToRegexp} = require("path-to-regexp");let needToToken = [{method:"GET",path:"/user"},{method:"DELETE",path:"/user/:id"},{method:"PUT",path:"/user/:id"},]//测试path-to-regexp// function test(){// let reg = pathToRegexp("/user/:id");// console.log(reg.test("/user/1"));// }// test();//由于/api/user/:id真正对应的是/api/user/123这样的URI路径//因此,为了匹配是否URI路径对应,使用path-to-regexp模块module.exports = function(req,res,next){console.log("------->tokenMiddleware----->" + req.path + "------>" + req.method);let apis = needToToken.filter(item => {let reg = pathToRegexp(item.path);let flag = reg.test(req.path);return item.method == req.method && flag});console.log(apis.length);//如果apis数组中没有数据,证明没有需要过滤的页面if(apis.length <= 0){next();return;}let token = req.cookies.token;//如果cookie中没有,从req.headers.authorization取出if(!token){token = req.headers.authorization;}if(!token){res.send(resultUtil(null, 100, "请先登录", 1))return;}next();}
在后端index.js中,
