You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 加密和JWT工具
*
* 功能:
* 1. 密码加密和验证使用bcrypt
* 2. JWT token的生成和验证
*/
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
require('dotenv').config();
/**
* 密码加密
* @param {string} password - 原始密码
* @returns {Promise<string>} 加密后的密码
*
* 说明bcrypt会自动加"盐",同一个密码每次加密结果都不同,但都能正确验证
*/
const hashPassword = async (password) => {
try {
// 生成盐salt10是加密强度数字越大越安全但越慢
const salt = await bcrypt.genSalt(10);
// 使用盐加密密码
const hashedPassword = await bcrypt.hash(password, salt);
return hashedPassword;
} catch (error) {
throw new Error('密码加密失败: ' + error.message);
}
};
/**
* 密码验证
* @param {string} password - 用户输入的密码
* @param {string} hashedPassword - 数据库中存储的加密密码
* @returns {Promise<boolean>} 密码是否正确
*/
const comparePassword = async (password, hashedPassword) => {
try {
// bcrypt.compare会自动处理盐的比对
const isMatch = await bcrypt.compare(password, hashedPassword);
return isMatch;
} catch (error) {
throw new Error('密码验证失败: ' + error.message);
}
};
/**
* 生成JWT token
* @param {object} payload - 要存储在token中的数据通常是用户ID和角色
* @param {string} expiresIn - token过期时间如 '24h', '7d'
* @returns {string} JWT token字符串
*
* 说明JWT token就像一个电子身份证包含用户信息服务器可以验证真伪
*/
const generateToken = (payload, expiresIn = process.env.JWT_EXPIRES_IN || '24h') => {
try {
// 从环境变量获取密钥
const secret = process.env.JWT_SECRET;
if (!secret) {
throw new Error('JWT_SECRET 未配置');
}
// 签名生成token
const token = jwt.sign(payload, secret, { expiresIn });
return token;
} catch (error) {
throw new Error('Token生成失败: ' + error.message);
}
};
/**
* 验证JWT token
* @param {string} token - 要验证的token
* @returns {object} 解密后的数据
*
* 说明验证token是否有效、是否过期、是否被篡改
*/
const verifyToken = (token) => {
try {
const secret = process.env.JWT_SECRET;
if (!secret) {
throw new Error('JWT_SECRET 未配置');
}
// 验证并解密token
const decoded = jwt.verify(token, secret);
return decoded;
} catch (error) {
if (error.name === 'TokenExpiredError') {
throw new Error('Token已过期请重新登录');
} else if (error.name === 'JsonWebTokenError') {
throw new Error('无效的Token');
} else {
throw new Error('Token验证失败: ' + error.message);
}
}
};
// 导出所有函数
module.exports = {
hashPassword,
comparePassword,
generateToken,
verifyToken
};