Day17-Session 管理(一)

前言

在了解 cookie 的安全性设定之後,接下来的两天要来讲讲跟 session 安全性有关的注意事项

很多网站在你输入帐号密码按下登入之後,会产生一串长长的 session ID 存在资料库,然後把这串 ID 利用 Set-Cookie 存到你的 cookie 里面去,如此一来当你下次从浏览器发出请求时,因为 cookie 里面的 session ID 会一起被带上,所以 API Server 就可以根据这个 ID 判断你是谁,然後让你进行发文、留言等等操作

Session ID 长什麽样

光用讲的太抽象了,我们来看看各网站的 session id 都长什麽样子,首先这是 Gmail 的例子,在经过二阶段验证之後,他会给我一串 session ID 叫做 SIDCC,目测超过 100 个英数字(真的有够长)

而我最近用来找房子的 591,他也是给一串很长的 session ID 叫做 591_new_session,整串将近 300 字,而且在众多 cookie 里面只有他被加上 HttpOnly,显示这个 cookie 的安全性特别重要

那为什麽 session ID 都要这麽长呢?答案就是因为这样才不会太容易被猜中。如果你的 session ID 只有五位数字,那基本上我只要写个程序花点时间从 00000 试到 99999,应该就可以试出很多可用的 ID,再来就可以用这些 ID 轻易的假冒别人的身分进行各种操作

你的 ID 够乱吗

Session ID 光长是没用的,因为如果只有长但却不够乱,那就很容易被猜出来。譬如说我就曾经看过 API Server 用看起来像是 MongoDB ObjectId 的东西当作 session ID,像是 507f1f77bcf86cd799439011

虽然由 MongoDB 自动建立的 ObjectId 看起来很长,但那个 ObjectId 其实是从 timestamp 转过去的,因此只会增加不会减少,而且增加的速度也不会太快。知道了这个特性之後,我就一样可以写个程序去猜别人的 Session ID,猜到了之後就可以冒用别人的身份

实际范例

知道 Session ID 要够长、够乱之後,那在实际开发中应该怎麽做呢?说真的并不用特别做什麽,因为各框架几乎都有比较热门的 session 管理 library,只要好好善用他们不要自作聪明拿资料库的 auto increment ID 来当 session ID 就好了

像如果你是写 express 的话 express-session 就非常好用,你只需要直接用它当作 middleware,他就会自动帮你在浏览器上存一个够长、够乱、够安全的 session ID,而且你也可以在这个 session object 中放各种使用者的资讯,需要时就可以拿出来用

var session = require('express-session');

app.use(session({
    secret: 'larry_is_handsome',  // 用来验证 cookie 有没有被篡改的 secret
    cookie: { secure: true }
}));

app.post('/login', function(req, res, next){
    // 登入时用信箱、密码找找看有没有这个使用者
    const user = db.users.findOne({ email: req.body.email, password: hash(req.body.password) })
    if (!user) { res.send('Invalid username or password') }
    
    // 把这个 session 对应到使用者的 ID
    req.session.userId = user._id
    res.send('登入成功')
});

app.get('/api/whoami', function(req, res, next){
    // 用 session 里面储存的 userId 去找使用者,就可以知道请求是谁发过来的
    const user = db.users.findOne({ _id: req.session.userId })    
    res.send(`你好啊 ${user.name} !`)
});

而 Go 的话也有一个 sessions package 可以用,因为用起来跟 express 非常像,去读一下它的文件应该就会用,所以这边就不写范例了~

小结

今天讲解了两个跟 session ID 安全性有关的注意事项,虽然最後的结论是不用特别做什麽、直接去用别人造好的轮子就好,但至少你在用的时候会知道怎麽识别这些第三方套件的安全性,不会到真的出事时才发现这个别人造的轮子偷工减料、一上路就破,到时真的会欲哭无泪


<<:  第17天~ListView再练一个

>>:  Day 17: LeetCode 1143. Longest Common Subsequence

Day3 中秋就是要烤肉阿-美式烤猪肋排

中秋就是要烤肉阿 虽然今年因为疫情无法在外群聚烤肉,但仪式感不能少,自己在家烤起来! 这次来点不一样...

android studio 30天学习笔记 -day 22-Dagger 前言

Dependency Injection Dependency Injection中文翻译为依赖注入...

从零开始学3D游戏设计:基础粒子效果

这是 Roblox 从零开始系列,在效果章节的单元,今天你将学会如何透过粒子发射器来做出基本的粒子特...

Dungeon Mizarka 030

今天是铁人赛事的第30天,利用这篇文章总结这一个月以来的过程。 游戏调整目标 如同文章系列一开始所提...

在 React Native 里实作 NSFW (Not suitable for work,工作场合不宜) 分类器

需求与场景 虽然我们的 App 为了怕麻烦,有要求 18+ 以上才能使用,但还是怕会有绕过这个限制的...