3.1 暗号和钥匙-Cookie和Session的区别
Cookie和Session的区别
小奈:表哥那个cookie和session有什么区别
大仁:记得上次了小明和你讲的故事么?, 在浏览器输入url背后发现的事。 2.1 初次见面-浏览器输入url后
大仁:上次输入的网址 www.hellojack.com ,其实完整的是 http://www.hellojack.com,前面有个http前缀,它是一个协议,无状态协议。
大仁:我来给你讲个故事吧。
http
很久很久以前(30年前,只有静态html的时候),有个发快递的人叫http。
偶尔有人打电话(无来电显示)向他买东西,他收到请求后,就会去中心仓库克隆一份这个东西,然后把货品塞到管道里,这样客人就收到了。
那时候工作很轻松,小日子过的挺舒服啊。
好景不常(社区、电商网站的出现),仓库里进了很多贵重和私密物品。
老板要求他记录订购贵重物品的客人,私密物品一定要鉴别客人身份。
暗号:cookie
但是没有来电显示啊,鬼知道谁定的,http就很苦恼了。
想了想,终于想到一个办法了。
以后客人打电话过来,我就给他个暗号。
终于可以记录了,但是又遇到了一个问题。
由于暗号比较简单,其他客人可以伪造。
档案袋和钥匙:session和session-id
http想了很久,最后和服务器协商,让服务器那边建立档案袋,并把钥匙给客人,下次叫客人把钥匙给他。之后客人都通过钥匙来打开档案袋,确定身份。如果打不开的话就证明错了。
我是邪恶的代码分割线
express 中的 cookie
express 在 4.x 版本之后,session管理和cookies等许多模块都不再直接包含在express中,而是需要单独添加相应模块。
imagevar express = require('express');
// 首先引入 cookie-parser 这个模块
var cookieParser = require('cookie-parser');
var app = express();
app.listen(3000);
// 使用 cookieParser 中间件,cookieParser(secret, options)
app.use(cookieParser());
app.get('/', function (req, res) {
// 如果请求中的 cookie 存在 isVisit, 则输出 cookie
// 否则,设置 cookie 字段 isVisit, 并设置过期时间为1分钟
if (req.cookies.jack) {
console.log(req.cookies.jack);
res.send("welcome");
} else {
res.cookie('jack', 'content', {maxAge: 60 * 1000});
res.send("no cookie");
}
});
这里开发调试的时候用supervisor来启动,代码有改动,它会自动重启,避免不必要的手动重启工作。
image新版本的开发者工具界面,在application里面可以看到cookies 这些存储
image现在我们看到一个cookie名字为jack 内容为content的cookie就存储了,时间期限也有。
如果没有设置时间(maxage/expires),
那就是session cookie,
浏览器关闭的时候cookie就没了。
session
cookie 虽然很方便,但是使用 cookie 有一个很大的弊端,cookie 中的所有数据在客户端就可以被修改,数据非常容易被伪造,那么一些重要的数据就不能存放在 cookie 中了,而且如果 cookie 中数据字段太多会影响传输效率。为了解决这些问题,就产生了 session,session 中的数据是保留在服务器端的。
session 的运作通过一个session_id来进行。session_id通常是存放在客户端的 cookie 中,比如在 express 中,默认是connect.sid这个字段,当请求到来时,服务端检查 cookie 中保存的 session_id 并通过这个 session_id 与服务器端的 session data 关联起来,进行数据的保存和修改。
这意思就是说,当你浏览一个网页时,服务端随机产生一个 1024 比特长的字符串,然后存在你 cookie 中的connect.sid字段中。当你下次访问时,cookie 会带有这个字符串,然后浏览器就知道你是上次访问过的某某某,然后从服务器的存储中取出上次记录在你身上的数据。由于字符串是随机产生的,而且位数足够多,所以也不担心有人能够伪造。伪造成功的概率比坐在家里编程时被邻居家的狗突然闯入并咬死的几率还低。
session 可以存放在 1)内存、2)cookie本身、3)redis 或 memcached 等缓存中,或者4)数据库中。线上来说,缓存的方案比较常见,存数据库的话,查询效率相比前三者都太低,不推荐;cookie session 有安全性问题,下面会提到。
express 中操作 session 要用到express-session(https://github.com/expressjs/session) 这个模块,主要的方法就是session(options),其中 options 中包含可选参数,主要有:
name: 设置 cookie 中,保存 session 的字段名称,默认为connect.sid。
store: session 的存储方式,默认存放在内存中,也可以使用 redis,mongodb 等。express 生态中都有相应模块的支持。
secret: 通过设置的 secret 字符串,来计算 hash 值并放在 cookie 中,使产生的 signedCookie 防篡改。
cookie: 设置存放 session id 的 cookie 的相关选项,默认为
(default: { path: '/', httpOnly: true, secure: false, maxAge: null })
genid: 产生一个新的 session_id 时,所使用的函数, 默认使用uid2这个 npm 包。
rolling: 每个请求都重新设置一个 cookie,默认为 false。
resave: 即使 session 没有被修改,也保存 session 值,默认为 true。
1) 在内存中存储 session
express-session默认使用内存来存 session,对于开发调试来说很方便。
var express = require('express');
// 首先引入 express-session 这个模块
var session = require('express-session');
var app = express();
app.listen(5000);
app.use(cookieParser('jack2016'));
//解析cookie secret为‘jack2016’的cookie,可不可以不写secret?不写会报错
}));
// 按照上面的解释,设置 session 的可选参数
app.use(session({
secret:'jack2016',
// 建议使用 128 个字符的随机字符串,这里不写secret的话cookie存储的是不加密的sessionid
name:'jacks', //cookie名字,这里cookie存的内容是用secret加密的sessionid, cookie: {maxAge:60*2000},//cookie设置,maxAge设置时间好像受到限制,太小直接没效,设置的够大无论是60*60还是60*60*24*12好像都是固定的4小时,这里有点疑惑。
}));
/* GET home page. */
router.get('/',function(req,res,next) {
console.log(req.sessionID,req.cookies.jack,req.signedCookies.jack);
res.render('index',{title:'Express'});
});
关注专题
欢迎来这里:产品经理的技术修养投稿,关于李大仁的剧情、产品、技术教程等等,关注能获取更多。
代码在这里
如果真要提升技术修养,肯定要实战啊,可选。
有兴趣的加入此群,GitHub上也有实战代码。
Github地址: 一个代码分享托管网站
群名称:一起学Javascript
群 号:537728988