深入剖析Express cookie-parser中间件实现示例

2020-06-17 07:23:20易采站长站整理

cookie签名、验证实现剖析

Express完成cookie值的签名, cookie-parser 实现签名cookie的解析。两者共用同一个秘钥。

cookie签名

Express对cookie的设置(包括签名),都是通过 res.cookie() 这个方法实现的。

精简后的代码如下:


res.cookie = function (name, value, options) {
var secret = this.req.secret;
var signed = opts.signed;
// 如果 options.signed 为true,则对cookie进行签名
if (signed) {
val = 's:' + sign(val, secret);
}
this.append('Set-Cookie', cookie.serialize(name, String(val), opts));
return this;
};

sign 为签名函数。伪代码如下,其实就是把cookie的原始值,跟hmac后的值拼接起来。

敲黑板划重点:签名后的cookie值,包含了原始值。


function sign (val, secret) {
return val + '.' + hmac(val, secret);
}

这里的

secret 
哪来的呢?是
cookie-parser 
初始化的时候传入的。如下伪代码所示:


var cookieParser = function (secret) {
return function (req, res, next) {
req.secret = secret;
// ...
next();
};
};
app.use(cookieParser('secret'));

签名cookie解析

知道了cookie签名的机制后,如何”解析”签名cookie就很清楚了。这个阶段,中间件主要做了两件事:

将签名cookie对应的原始值提取出来
验证签名cookie是否合法

实现代码如下:


// str:签名后的cookie,比如 "s:chyingp.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0"
// secret:秘钥,比如 "secret"
function signedCookie(str, secret) {

// 检查是否 s: 开头,确保只对签过名的cookie进行解析
if (str.substr(0, 2) !== 's:') {
return str;
}

// 校验签名的值是否合法,如合法,返回true,否则,返回false
var val = unsign(str.slice(2), secret);

if (val !== false) {
return val;
}

return false;
}

判断、提取cookie原始值比较简单。只是是 unsign 方法名比较有迷惑性。

一般只会对签名进行合法校验,并没有所谓的反签名。

unsign 
方法的代码如下:

首先,从传入的cookie值中,分别提取出原始值A1、签名值B1。
其次,用同样的秘钥对A1进行签名,得到A2。
最后,根据A2、B1是否相等,判断签名是否合法。

exports.unsign = function(val, secret){