状态管理: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(";");
//判断是否有名字叫token
for (let i = 0; i < cookieArr.length; i++) {
let item = cookieArr[i];
//每一个cookie都是一个键值对 xxx=xxxxx
let 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中,