在MEAN应用中返回用户模型的salt与hash数据是否安全?
绝对不合理,而且非常不安全!
先直接给结论:返回用户的salt和hash字段是严重的安全漏洞,绝对不能这么做,原因如下:
- 直接降低密码哈希的安全性:salt的作用是防止攻击者用彩虹表批量破解多个密码哈希,但如果攻击者同时拿到了你的用户hash和对应的salt,他们就可以针对这个特定组合直接发起暴力破解/字典攻击——不需要再依赖彩虹表,等于把破解的门槛直接降低了。哪怕你用了pbkdf2Sync这种慢哈希算法,泄露这两个字段也会让攻击者有机会逐步尝试破解用户密码。
- 完全无业务必要:前端或客户端根本不需要知道这两个字段,它们只是后端用来验证用户密码的内部计算值,返回出去对业务逻辑没有任何帮助,纯粹是给自己加安全风险。
怎么修复这个问题?
给你两个简单可靠的方案,选一个适合你的就行:
方案1:在Schema里默认隐藏这两个字段
修改你的mongoose Schema,给hash和salt加上select: false,这样默认查询时不会返回这两个字段:
var UsersSchema = new mongoose.Schema({ // 其他字段保持不变... hash: { type: String, select: false }, salt: { type: String, select: false }, // 其他字段保持不变... });
如果后续后端需要验证密码(比如登录时),可以手动指定查询这两个字段:
User.findOne({ username: req.body.username }).select('+hash +salt').exec(...);
方案2:转换JSON时自动移除字段
给Schema配置toJSON的transform函数,这样每次把用户文档转成JSON返回时,都会自动删掉salt和hash:
UsersSchema.set('toJSON', { transform: function(doc, ret) { // 删除不需要返回的敏感字段 delete ret.hash; delete ret.salt; // 也可以顺便删掉_id或者其他你不想返回的字段 // delete ret._id; return ret; } });
这样不管是创建用户还是查询用户列表,返回的JSON里都不会包含这两个敏感字段了。
另外顺便提一句:你代码里把JWT密钥硬写成"MY_SECRET"的做法也很危险,一定要改成用环境变量存储(比如process.env.JWT_SECRET),绝对不能把密钥直接写在代码里提交到版本库!
内容的提问来源于stack exchange,提问作者Dr oscar
相关产品推荐
相关产品推荐

