Node.js新手求助:分离加密函数后出现ReferenceError: userData is not defined
解决加密函数分离后的「ReferenceError: userData is not defined」问题
嗨,我来帮你搞定这个问题~你遇到的错误核心原因很简单:模块之间的变量作用域是完全独立的,encryption.js里的encryption函数根本访问不到authentication.js里定义的userData变量。要解决这个问题,我们需要让两个模块通过「参数传递」来共享数据,同时还要让加密函数返回加密后的结果,这样主文件才能拿到可用的加密密码。
第一步:重构encryption.js,让它接收参数并返回结果
原来的encryption函数既没接收外部数据,也没把加密后的encrypted值暴露出去,我们需要调整它的逻辑:
// encryption.js const crypto = require('crypto'); // 把require提到模块顶部,不要放在函数内部 function encryption(userPassword) { // 接收需要加密的用户密码作为参数 const algorithm = 'aes-192-cbc'; // 注意:同步的scryptSync会阻塞事件循环,建议后续改用异步的crypto.scrypt() const key = crypto.scryptSync(userPassword, 'salt', 24); // 重要提示:不要用固定的iv!每次加密生成随机iv才更安全 const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv(algorithm, key, iv); let encrypted = ''; cipher.on('readable', () => { let chunk; while (null !== (chunk = cipher.read())) { encrypted += chunk.toString('hex'); } }); cipher.write(userPassword); // 这里加密传入的用户密码,而不是固定文本 cipher.end(); // 如果后续需要解密,记得把iv和加密结果一起返回(比如返回{ encrypted, iv }) return encrypted; } module.exports = { encryption };
小修正:原来的代码里写了
cipher.write('some clear text data'),这是固定测试文本,我已经帮你改成加密传入的用户密码了,这才符合你的业务需求。
第二步:修改authentication.js里的调用逻辑
现在encryption函数需要接收密码参数,并且会返回加密后的结果,所以调用时要传参并接收返回值:
// authentication.js里的register路由片段 router.post('/register', (req, res) => { const userData = req.body; User.findOne({ email: userData.email }, (error, user) => { // ... 省略其他判断逻辑 ... else { // 调用加密函数,传入用户密码,接收加密后的结果 const encrypted = encryption(userData.password); const user = new User({ firstname: userData.firstname, email: userData.email, surname: userData.surname, password: encrypted }); // ... 省略后续保存和返回逻辑 ... } }) })
额外的优化建议
- 尽量避免使用同步的
crypto.scryptSync,因为同步操作会阻塞Node.js的事件循环,影响服务性能。建议改用异步的crypto.scrypt(),配合async/await语法会更优雅。 - 如果是存储用户密码,其实更推荐使用专门的密码哈希算法(比如bcrypt),而不是AES对称加密——因为AES可以逆向解密,而密码哈希是单向不可逆的,更符合用户密码存储的安全规范。
内容的提问来源于stack exchange,提问作者user12933680
相关产品推荐
相关产品推荐

