Cookie签名后为什么还是能被篡改?

皇甫令敏 阅读 62

我用 Express 的 cookie-parser 中间件加了签名,但发现用户手动改 Cookie 值后,服务端居然没报错,还能正常解析,这不就等于没签名吗?

我代码是这样写的:

const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser('my-secret-key')); // 设置签名密钥

app.get('/set', (req, res) => {
  res.cookie('token', 'abc123', { signed: true });
  res.send('Cookie set');
});

app.get('/get', (req, res) => {
  console.log(req.signedCookies.token); // 即使前端改了 token 值,这里有时还能输出?
  res.send(req.signedCookies.token || 'none');
});

是不是我哪里理解错了?签名不是应该防止篡改的吗?

我来解答 赞 13 收藏
二维码
手机扫码查看
2 条解答
FSD-朝曦
我之前踩过这个坑,刚开始也觉得挺纳闷的。其实问题出在你对签名 cookie 的理解上。签名 cookie 并不是防篡改的,而是为了验证 cookie 是否被篡改过。也就是说,当你设置了签名密钥后,服务器会在设置 cookie 时生成一个哈希值,并附带在 cookie 后面。当客户端返回这个 cookie 时,服务器会用相同的密钥重新计算哈希值,然后跟客户端传回来的哈希值对比。如果对不上,说明 cookie 被篡改了。

在你的代码里,req.signedCookies.token 是未定义或者 false 时才会输出 'none'。但是,如果你手动改了 cookie 值,实际上 req.signedCookies.token 会是 falseundefined,而不是原来的值。你可能有时候看到输出,是因为浏览器没有更新 cookie 值,或者是其他原因导致的。

正确的做法是检查 req.signedCookies.token 是否为 falseundefined 来判断 cookie 是否被篡改。你可以这样修改你的代码:

app.get('/get', (req, res) => {
if (req.signedCookies.token === undefined || req.signedCookies.token === false) {
res.send('Cookie has been tampered with or is missing');
} else {
res.send(req.signedCookies.token);
}
});


这样就能正确识别出 cookie 是否被篡改了。希望这能帮到你,别再被这个问题坑了。
点赞
2026-03-23 13:14
技术雯雯
你理解错了签名的工作方式,cookie-parser 签名验证失败时不会报错,而是直接返回 false 或 undefined。

签名的实际机制是这样的:设置 signed cookie 时,cookie-parser 会把值和签名拼在一起,格式大概是 abc123.sigHASH,分成两部分用 . 分隔。当读取时,它会重新计算签名然后比对,如果不一致就直接返回 false,不会抛异常。

你的代码里 req.signedCookies.token 有时还能输出,可能是因为:

1. 你改的是原始值,没改签名部分,或者
2. 你同时改了值和签名(虽然概率很低)

正确用法是必须手动判断返回值:

app.get('/get', (req, res) => {
const token = req.signedCookies.token;

// 必须判断是否是 false(签名验证失败会返回这个)
if (token === false) {
return res.status(403).send('Cookie被篡改了');
}

if (!token) {
return res.send('none');
}

res.send(token);
});


还有一点要确认——你读的是 req.signedCookies 还是 req.cookies?后者是原始未签名的值,任何改法都能读到。签名 cookie 必须走 signedCookies 这个属性。

签名防篡改的原理其实就是这样:服务端重新计算签名比对,不一致就当无效处理,不会报错。这是常规做法,不是你的问题,是 cookie-parser 的设计风格比较"温柔"。
点赞
2026-03-14 03:14