建议先看这篇文章:浏览器 cookie 的原理(详) 介绍了身份验证的步骤:
简单来说,服务器向客户端发送的【出生证】就是一个 cookie 信息,客户端收到后保存在硬盘中,之后的请求会自动带上对应的 cookie,服务器验证 cookie 信息成功后,允许之后的操作。
一般来说,session 和 cookie 是联合起来使用的,简单的数据放 cookie,复杂的放 session。
关键点有2个:
key=value
中的 value
是如何生成的?value
有2种形式,一种是 jwt令牌,一种就是 sessionId。
session 是保存在服务器端的键值对,通过 sessionId 和客户端关联。sessionId 一般会使用 uuid(全球唯一标识码:Universally Unique Identifier)来表示(可通过时间戳,mac 地址,计数器等通过算法实现)。
对比出入证 sessionId 即可。
因为浏览器关闭并不会主动通知服务器,所以即便 cookie 是会话级别(默认过期时间),关闭浏览器 cookie 删除,也不会影响到服务器的 session,所以需要一些手段让服务器认为客户端已经停止了活动,把 session 删除以节省空间。
当服务器设置过期时间后,当客户端长时间没有传递 sessionId 过来时,服务器即可自动清除 session。
使用 js 监听页面关闭或其他退出操作,此时通知服务器删除 session。
cookie | session | |
---|---|---|
存储位置 | 客户端,不占用服务器资源 | 服务器,占用服务器资源 |
存储格式 | 仅字符串 | 任意格式 |
存储大小 | 每个网站仅 4kb | 理论上无上限 |
安全性 | 易被获取和篡改,易丢失 | <-- 相反 |
(实际不可能这样做)如果这样做的话,那就绕开验证了:随便填别人的手机号,在 cookie 中获取验证码就能登录了。
可通过 session 机制来解决:
可以使用中间件 koa-session 来更容易的操作 session。
默认情况下,
koa-session
会将 session 保存在服务器的内存中。也就是说,重启服务器就会清空,测试时需注意。
const Koa = require("koa");
const Router = require("koa-router");
const { bodyParser } = require("@koa/bodyparser");
const session = require("koa-session");
const app = new Koa();
const router = new Router();
app.keys = ["some secret hurr"];
app.use(session(app));
router.post("/api/login", (ctx) => {
const { name, pwd } = ctx.request.body;
if (name === "下雪天的夏风" && pwd === "123") {
ctx.session.id = name;
ctx.body = "登录成功";
ctx.response.redirect("/api/home");
} else {
ctx.body = {
code: 500,
msg: "用户名或密码错误",
};
}
});
router.get("/api/home", (ctx) => {
if (ctx.session.id) {
ctx.body = "home";
} else {
ctx.body = {
code: 500,
msg: "未登录",
};
}
});
router.get("/api/logout", (ctx) => {
// 清空登录信息
ctx.session = null;
ctx.body = "退出登录";
});
app.use(bodyParser()).use(router.routes());
app.listen(3001);
<form action="http://localhost:3001/api/login" method="post">
<input type="text" name="name" />
<input type="password" name="pwd" />
<button>提交</button>
</form>
效果:
注意到退出登录后,浏览器端的 cookie 就删除了。这是因为当调用 logout
接口时会设置 ctx.session = null
,会向浏览器添加如下 cookie,有效期设置为过去的时间,所以直接删除了。同时服务器中对应的 session 也会被清空。
以上。