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

皇甫令敏 阅读 3

我用 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');
});

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

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
技术雯雯
你理解错了签名的工作方式,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