使用Crypto-JS解密密码结果异常的登录验证问题求助
问题描述
在TypeScript环境下实现用户注册登录功能,使用Crypto-JS加密密码存入MongoDB,注册流程正常,加密后的密码与MongoDB中存储的一致,但登录时始终返回"wrong password"错误。打印日志发现:
inputPassword显示正确的输入密码originalPassword仅包含原密码中的数字,顺序混乱且长度翻倍
已尝试搜索相关问题、清理缓存,均未解决。以下是auth.ts代码:
import { Router, Request, Response } from "express"; const authRouter = Router(); const CryptoJS = require('crypto-js'); import * as jwt from 'jsonwebtoken'; import User from "../models/user"; // 注册 authRouter.post('/register', async (request:Request, response:Response)=>{ const newUser = new User({ vorname:request.body.vorname, nachname:request.body.nachname, email:request.body.email, username:request.body.username, street:request.body.street, number:request.body.number, plz:request.body.plz, city:request.body.city, password: CryptoJS.AES.encrypt( request.body.password, process.env.PASS_SEC ).toString(), }); try{ const savedUser = await newUser.save(); response.status(200).json(savedUser); } catch(error){ response.status(403) throw new Error('Action failed'); } }); // 登录 authRouter.post('/login', async (request:Request, response:Response)=>{ let sec:string = process.env.JWT_SEC as string; try{ const user = await User.findOne({username:request.body.username}); if(!user){ return response.status(401).json("Wrong credentials"); } const hashedPassword = CryptoJS.AES.decrypt(user?.password, process.env.PASS_SEC); console.log(hashedPassword); const originalPassword = hashedPassword.toString(CryptoJS.enc.UTF8); console.log(originalPassword); const inputPassword = request.body.password; console.log(inputPassword); if(originalPassword != inputPassword){ return response.status(401).json("Wrong password"); } else { const accessToken = jwt.sign( {id: user!._id, isAdmin:user!.isAdmin, }, sec, {expiresIn:"30d"} ) const {password, ...others} = user?._doc; response.status(200).json({...others, accessToken}); } } catch(error:any){ response.status(401) throw new Error(error) } }); export default authRouter;
解决方案
1. 修正CryptoJS导入方式
TypeScript环境下建议使用ES模块导入替代CommonJS的require,避免类型不兼容导致的加密解密逻辑异常:
// 替换原require语句 import CryptoJS from 'crypto-js';
2. 验证环境变量密钥的一致性与有效性
- 在注册和登录逻辑中添加日志,确认
process.env.PASS_SEC的取值完全一致:// 注册时添加 console.log('Register PASS_SEC:', process.env.PASS_SEC); // 登录时添加 console.log('Login PASS_SEC:', process.env.PASS_SEC); - AES加密要求密钥长度为128/192/256位(对应16/24/32个ASCII字符),若密钥长度不符合要求,CryptoJS会自动调整但可能引发解密错误,建议设置符合规范的密钥。
3. 增加解密有效性校验
解密失败时,toString(CryptoJS.enc.UTF8)会返回空字符串或乱码,可在代码中添加判断提前拦截:
const originalPassword = hashedPassword.toString(CryptoJS.enc.UTF8); // 新增解密失败判断 if (!originalPassword) { return response.status(401).json("Password decryption failed"); }
4. 确认MongoDB字段类型
检查User模型中password字段的类型是否为String,避免因类型不匹配导致存储/读取时的字符串损坏:
// user.ts 模型示例 import mongoose from "mongoose"; const UserSchema = new mongoose.Schema({ vorname: String, nachname: String, email: String, username: String, street: String, number: String, plz: String, city: String, password: { type: String, required: true }, isAdmin: { type: Boolean, default: false } }); export default mongoose.model("User", UserSchema);
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

