node.js - 在 Typeorm SQL 中使用 Node、Express、JWT 重置密码
问题描述
我的密码重置功能 ( changepass
) 有问题,这可能是我的代码的一个小错误。
通过 nodemailer 处理新密码并成功登录后,我尝试实现允许用户更新密码的下一个功能。
用户登录后,我的身份验证中间件在所有其他功能中都能正常工作。
登录后,我在正文上提交旧密码和新密码,在Bearer Token
字段中提交新令牌。令人惊讶的是,我得到了状态 204,因为它一直有效。
在终端上,我不断收到以下信息:
const id = res.locals.userId; -> undefined;
No metadata found. There is more than once class-validator version installed probably. You need to flatten your dependencies.
该功能确实做了一些事情,但是它无法再用旧密码和新密码登录,所以我需要再次通过nodemailer请求新密码。
有人知道我的错误在哪里吗?
密码重置(问题出在哪里):
async changepass(req: Request, res: Response) {
// Get ID from JWT
const id = res.locals.userId;
console.log(id)
// Get parameters from the body
const { oldPassword, newPassword } = req.body;
if (!(oldPassword && newPassword)) {
res.status(400).send();
}
// Get user from the database
const userRepository = getRepository(User);
// let user = await userRepository.findOneOrFail(id);
let user = User as any;
try {
user = await userRepository.findOneOrFail(id);
} catch (id) {
res.status(401).send();
}
// Check if old password matches
if (!user.checkIfUnencryptedPasswordIsValid(oldPassword)) {
res.status(401).send();
return;
}
// Validate the model (Password length)
user.password = newPassword;
const errors = await validate(user);
if (errors.length > 0) {
res.status(400).send(errors);
return;
}
// Hash the new password and save
user.hashPassword();
userRepository.save(user);
res.status(204).send();
},
用户登录:
async login(req: Request, res: Response) {
// Get user from database
const userRepository = getRepository(User);
const { email, password } = req.body;
// Check if useremail and password are set
if (!(email && password)) {
console.error('Empty name or password!');
return res.status(400).send({
error: 'Empty name or password'
});
}
const user = await userRepository.findOne({ where: { email } });
if(!user) {
return res.sendStatus(401);
}
// Check if encrypted password match : checkIfUnenc... função vemm do model
if (!user.checkIfUnencryptedPasswordIsValid(password)) {
return res.status(401).send({
error: 'Cannot match encrypted password'
});
}
// Sing JWT, valid for 1 hour
const token = jwt.sign(
{ id: user.id, email: user.email }, //payload do token, informações do user
config.jwtSecret, //chave secreta que autoriza, ideal no .env
{ expiresIn: "1d" }
);
// Send the jwt in the response
res.json({
user,
token
});
},
路线:
//change password route
routes.post('/users/changepass', checkJwt, UserController.changepass);
认证中间件:
interface TokenPayload {
id: number;
iat: string;
exp: string;
}
export default function checkJwt(req: Request, res: Response, next: NextFunction) {
const { authorization } = req.headers;
// console.log(authorization)
if(!authorization) {
return res.sendStatus(401)
}
const token = authorization.replace("Bearer", "").trim(); //apenas remover a palavra "Bearer" e espaço
try {
const data = jwt.verify(token, config.jwtSecret)
//console.log(data) -> data traz no log o id, iat, exp, então tenho que tipar o data com interface
const { id } = data as TokenPayload;
req.userId = id;
console.log(id)
} catch {
return res.sendStatus(401);
}
next();
}
解决方案
推荐阅读
- javascript - 如何在像 Rfc2898DeriveBytes 这样的 javascript 中创建加密函数
- python - 我正在尝试使用 AJAX 将已渲染的 Django 模板注入我的页面的一部分
- python - 将 Django 从 SQLite 转换为 PostgreSQL
- java - Spring - 显式 bean 实例化未设置 @Value 属性
- ios - NSLayoutConstraint - 两项,一行,间距优先
- android - 如何在改造 2 上发布整个数据库
- xamarin.forms - 未应用 CornerRadius
- r - 在 R dplyr 中按组将多列转换为相对频率
- apache-spark - 在 PySpark Structured Streaming 中为多个输出流使用单个流数据帧
- c - 从C中的void函数返回一个值