文章目录加载中

身份认证-Session机制

# 认识 Session

Session 机制准确来说,也是通过 K-V 数据格式来保存状态。其中:

  • Key:也称 SessionID,保存在客户端浏览器。
  • Value:也称“Session”,保存在服务端。

可以看到,客户端只需要存储 SessionID。具体映射的数据结构放在了服务端,因此跳出了仅仅浏览器 cookie 只可以存储 string 类型的限制。

而客户端存储 SessionID,还是需要借助 cookie 来实现。

# 整体流程

假设/login接口登陆成功后,服务器可以生成 sessionId 和 session。其中,session 中保存了过期时间,一些冗余信息等。代码如下:

router.get("/login", async (ctx, next) => {
    const { user, pwd } = querystring.parse(ctx.request.search.slice(1));
    // mock数据,模拟一下登陆过程
    if (user === "test" && pwd === "123456") {
        // 生成客户端存储的sessinId
        const sessionId = crypto
            .createHash("md5")
            .update(user + pwd)
            .digest("hex");
        // 生成服务端存储的session
        const session = {
            expire: Date.now() + 1000 * 60 * 60 * 24, // 过期时间
            info: {
                // 保存的信息
                name: user
            }
        };
        sessions.set(sessionId, session);
        ctx.cookies.set("sessionId", sessionId);
        ctx.response.body = "登陆成功";
    } else {
        ctx.response.body = "登陆失败";
        ctx.response.status = 401;
    }
});

然后客户端在 cookies 中携带 sessionId,访问/userInfo接口,获得用户信息。服务端检查 sessionId 合法性,以及是否过期。代码如下:

router.get("/userInfo", async (ctx, next) => {
    const sessionId = ctx.cookies.get("sessionId");
    const session = sessions.get(sessionId);
    // 如果sessionId不存在
    if (!session) {
        ctx.response.body = "无法识别身份";
        ctx.response.status = 401;
        return;
    }
    // session过期
    if (session.expire <= Date.now()) {
        ctx.response.body = "session过期,请重新登陆";
        ctx.response.status = 401;
        return;
    }
    ctx.response.body = session.info;
});

打开 chrome dev tools,我们可以看到,http 请求自动携带了 cookie 中的

sessionId。并且通过后端检验,拿到了用户信息。

session 传输数据少,数据结构灵活:相较于 cookie 来说,session 存储在服务端,客户端仅保留换取 session 的用户凭证。因此传输数据量小,速度快。

session 更安全:检验、生成、验证都是在服务端按照指定规则完成,而 cookie 可能被客户端通过 js 代码篡改。

session 的不足:服务器是有状态的。多台后端服务器无法共享 session。解决方法是,专门准备一台 session 服务器,关于 session 的所有操作都交给它来调用。而服务器之间的调用,可以走内网 ip,走 RPC 调用(不走 http)。

本文来自心谭博客:xin-tan.com,经常更新web和算法的文章笔记,前往github查看目录归纳:github.com/dongyuanxin/blog