bcrypt.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. 'use strict';
  2. const bcrypt = require('bcryptjs');
  3. module.exports = app => {
  4. class Bcrypt extends app.BaseService {
  5. /**
  6. * 生成 Bcrypt 加盐哈希(自动生成随机盐)
  7. * @param {string} plainPassword 明文密码
  8. * @return {Promise<string>} bcrypt 加密后的哈希字符串
  9. */
  10. async generateBcryptHash(plainPassword) {
  11. try {
  12. const salt = await bcrypt.genSalt(10); // 纯 JS 异步生成,无阻塞
  13. // 2. 生成密码哈希(盐值自动拼接在哈希结果中,无需单独存储盐值)
  14. const hashedPassword = await bcrypt.hash(plainPassword, salt);
  15. return hashedPassword;
  16. } catch (error) {
  17. console.error('Bcrypt 哈希生成失败:', error);
  18. throw new Error('密码加密失败'); // 生产环境可封装为自定义错误
  19. }
  20. }
  21. /**
  22. * 验证 Bcrypt 哈希
  23. * @param {string} plainPassword 明文密码
  24. * @param {array<string>} storedBcryptHash 数据库存储的哈希字段数组
  25. * @return {Promise<boolean>} 验证结果
  26. */
  27. async verifyBcryptHash(plainPassword, storedBcryptHash = []) {
  28. if (!Array.isArray(storedBcryptHash) || storedBcryptHash.length === 0) {
  29. return false;
  30. }
  31. for (const hash of storedBcryptHash) {
  32. if (!hash || typeof hash !== 'string') {
  33. continue;
  34. }
  35. try {
  36. // 关键:不需要传 ARGON2_OPTIONS,哈希本身包含所有验证所需参数
  37. const isMatch = await bcrypt.compare(plainPassword, hash);
  38. if (isMatch) {
  39. return true;
  40. }
  41. } catch (error) {
  42. console.warn(`单个 Bcrypt 哈希验证出错(哈希值:${hash.substring(0, 20)}...):`, error);
  43. }
  44. }
  45. return false;
  46. }
  47. }
  48. return Bcrypt;
  49. };