客户端能否访问res.locals中存储的hashpassword等敏感字段?
问题背景
我在服务端把完整的user对象存在res.locals.loggedUser里,实现代码如下:
app.use(async (req, res, next) => { const user = await User.findById(req.session.userid); res.locals.loggedUser = user; next(); });
设置完res.locals.loggedUser之后,我可以在EJS模板里按如下方式访问数据,最终渲染后返回给客户端:
<% if(loggedUser) { %> <p>Your name: <%= loggedUser.name %></p> <% } %>
完整的user对象包含以下字段:
_id: { ObjectId("123abc") }, name: { type: String, required: [true, 'Your name is required.'] }, email: { type: String, required: [true, 'Email cannot be blank.'], unique: true }, phone: { type: Number, required: [true, 'You must provide your phone number.'], unique: true }, hashpassword: String, date: { joined: { type: Date } },
疑问
客户端能不能拿到user对象的其他字段,比如hashpassword?还是说res.locals只有服务端能访问?
解答
res.locals是仅服务端渲染模板时可访问的上下文变量,默认不会直接暴露给客户端,分两种情况判断是否会泄露敏感字段:
- 如果你当前的EJS模板和示例写法一致,只主动输出
name这类需要的字段,客户端完全拿不到hashpassword等其他字段:EJS的模板逻辑全部在服务端执行,最终返回给浏览器的只有渲染完成的静态HTML,里面只会包含你主动输出的内容,其余res.locals里的字段不会出现在响应包中。 - 如果你在模板里主动把完整的user对象序列化输出,比如写了
<%= JSON.stringify(loggedUser) %>把对象塞进前端JS变量或者页面文本里,那客户端就能拿到所有字段,包括hashpassword,会有严重的安全风险。
最佳实践建议
哪怕现在没有泄露风险,也建议你在给res.locals.loggedUser赋值的时候就过滤掉敏感字段,从根源避免后续写模板时不小心泄露:
// 只取需要的字段存入,去掉hashpassword等敏感内容 const { hashpassword, ...safeUser } = user.toObject(); res.locals.loggedUser = safeUser;
内容的提问来源于stack exchange,提问作者user15344186
相关产品推荐
相关产品推荐

