新功能: - 创建AI聊天助手组件(AIChatWidget) - 支持文字+图片多模态对话 - 集成Gemini AI API - 支持图片编辑和内容生成 - 实时对话历史管理 - 优雅的UI设计,支持黑夜模式 技术实现: - 后端API代理Gemini API(/api/ai-chat) - 支持最多5张图片上传 - 流式响应处理 - 对话历史管理 - Base64图片处理 配置: - 在.env中添加Gemini API配置 - GEMINI_API_KEY - GEMINI_API_BASE_URL - GEMINI_MODEL 替换原弹幕功能,提供更强大的AI助手体验!
109 lines
2.6 KiB
JavaScript
Executable File
109 lines
2.6 KiB
JavaScript
Executable File
const crypto = require('crypto');
|
||
const jwt = require('jsonwebtoken');
|
||
const dotenv = require('dotenv');
|
||
const bcrypt = require('bcryptjs');
|
||
|
||
dotenv.config();
|
||
|
||
// JWT密钥,应该存储在环境变量中
|
||
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-should-be-in-env';
|
||
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d';
|
||
|
||
/**
|
||
* 生成密码哈希
|
||
* @param {string} password - 原始密码
|
||
* @returns {Object} - 包含哈希密码和盐值
|
||
*/
|
||
function hashPassword(password) {
|
||
const salt = crypto.randomBytes(16).toString('hex');
|
||
const hash = crypto
|
||
.pbkdf2Sync(password, salt, 10000, 64, 'sha512')
|
||
.toString('hex');
|
||
return { hash, salt };
|
||
}
|
||
|
||
/**
|
||
* 验证密码
|
||
* @param {string} plainPassword - 明文密码
|
||
* @param {string} hashedPassword - 哈希密码
|
||
* @returns {Promise<boolean>} - 密码是否匹配
|
||
*/
|
||
const verifyPassword = async (plainPassword, hashedPassword) => {
|
||
try {
|
||
if (!plainPassword || !hashedPassword) {
|
||
throw new Error('密码验证失败:缺少必要参数');
|
||
}
|
||
|
||
const isMatch = await bcrypt.compare(plainPassword, hashedPassword);
|
||
return isMatch;
|
||
} catch (error) {
|
||
console.error('密码验证错误:', error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 生成JWT令牌
|
||
* @param {Object} payload - 令牌载荷
|
||
* @returns {string} - JWT令牌
|
||
*/
|
||
const generateToken = (payload) => {
|
||
try {
|
||
if (!payload || !payload._id) {
|
||
throw new Error('生成令牌失败:缺少必要参数');
|
||
}
|
||
|
||
const token = jwt.sign(
|
||
payload,
|
||
process.env.JWT_SECRET || 'your-secret-key',
|
||
{ expiresIn: '7d' }
|
||
);
|
||
|
||
return token;
|
||
} catch (error) {
|
||
console.error('生成令牌错误:', error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 验证JWT令牌
|
||
* @param {string} token - JWT令牌
|
||
* @returns {Object} - 解码后的载荷
|
||
*/
|
||
const verifyToken = (token) => {
|
||
try {
|
||
if (!token) {
|
||
throw new Error('验证令牌失败:缺少令牌');
|
||
}
|
||
|
||
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key');
|
||
return decoded;
|
||
} catch (error) {
|
||
console.error('验证令牌错误:', error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 从请求中提取令牌
|
||
* @param {Object} req - Express请求对象
|
||
* @returns {string|null} - JWT令牌或null
|
||
*/
|
||
function extractTokenFromRequest(req) {
|
||
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
|
||
return req.headers.authorization.substring(7);
|
||
}
|
||
if (req.cookies && req.cookies.token) {
|
||
return req.cookies.token;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
module.exports = {
|
||
hashPassword,
|
||
verifyPassword,
|
||
generateToken,
|
||
verifyToken,
|
||
extractTokenFromRequest
|
||
};
|