在签署 jwt 时,只保留 user_id 或整个用户对象是不是更好?
Posted
技术标签:
【中文标题】在签署 jwt 时,只保留 user_id 或整个用户对象是不是更好?【英文标题】:Is it better to keep just the user_id or the whole user object in the payload when signing a jwt?在签署 jwt 时,只保留 user_id 或整个用户对象是否更好? 【发布时间】:2021-01-30 11:19:15 【问题描述】:我知道有两种方法。
1) 传递整个用户对象:
let payload =
user:
id: user._id,
name:user.name,
email:user.email,
username:user.username
,
let token = jwt.sign(payload, process.env.JWT_SECRET, expiresIn: '1d' )
2) 仅传递 _id:
let token = jwt.sign( id: this._id , process.env.JWT_SECRET,
expiresIn: '1d',
);
在第二种方法中,每当我想访问受保护的路由时,我都必须使用存储在有效负载中的 _id 进行数据库调用以获取用户的详细信息。
// protect.js
// Verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = await User.findById(decoded.id);
虽然在第一种方法中,我始终拥有完整的用户详细信息对象,而无需进行额外的数据库调用。
在阅读了几篇博客之后,我开始知道我们应该保持我们的负载轻量级,但我心中的问题是,另一方面,我们必须在每次访问受保护的路由时进行单独的数据库调用。 我想知道哪种方法更有效。
提前感谢您的回答:)
【问题讨论】:
第一种方法可能更有效,但最大的缺点是,如果您使用第一种方法并且用户更改了他们的姓名、电子邮件等,那么您将使用不正确的信息。我总是会进行额外的数据库调用以确保您拥有正确的数据 【参考方案1】:使用 ID 签署 JWT 令牌,因为在初始创建后不太可能更改。
用户名和电子邮件等其他数据很容易发生变化。
编辑:这是我不久前做的一个练习的用户注册示例。希望能给大家一些帮助。
// POST api/users => Register user
router.post("/", (req, res) =>
const name, email, password = req.body;
// Simple validation
if (!name || !email || !password)
return res.status(400).json( msg: "Please enter required information" );
// Check for existing user
User.findOne( email ).then((user) =>
if (user) return res.status(400).json( msg: "User already exists" );
const newUser = new User(
name,
email,
password,
);
// Create salt and Hash
bcrypt.genSalt(10, (err, salt) =>
bcrypt.hash(newUser.password, salt, (err, hash) =>
if (err) throw err;
newUser.password = hash;
newUser.save().then((user) =>
jwt.sign(
id: user.id ,
jwtSecret,
expiresIn: 3600 ,
(err, token) =>
if (err) throw err;
res.json(
token,
user:
id: user.id,
name: user.name,
email: user.email,
,
);
);
);
);
);
);
);
【讨论】:
您的回答很有帮助,但不是很清楚。请使用示例详细说明,以便我可以将此答案标记为已接受。谢谢@K4R1。 @IbadShaikh 好的,添加了一个示例。希望它提供一些见解。我不是这些事情上最好的讲师/解释者。 例子中涉及到了MongoDB模型和bcrypt哈希,但是JWT部分明显存在。【参考方案2】:假设您有一个包含整个用户对象的有效负载,包括:
_id 姓名 电子邮件 用户名缺点案例:
假设用户后来编辑了他的名字,这意味着他的数据 在数据库中得到更新,但他的有效载荷仍然过时 旧名称,因为没有进行数据库调用来获取更新的记录。
如果用户现在尝试发出需要他的名字的 POST 请求 请求正文,然后将过时的名称推送到 数据库而不是他的新名字。
app.post('/event', auth, (req, res) =>
// creates an event with his old name.
// Because the current payload contains old name.
)
现在如果用户注销然后再次登录,令牌将 在有效负载中包含用户的新名称。
并且每当使用用户的新更新名称获取所有事件时 保存在有效负载中,最近创建的最新事件 不会获取旧名称,因为它包含旧名称 用户名。
根据我的知识,这是我能给出的最好的解释。 分享你的想法!
谢谢
【讨论】:
以上是关于在签署 jwt 时,只保留 user_id 或整个用户对象是不是更好?的主要内容,如果未能解决你的问题,请参考以下文章