| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- /**
- * 用户相关云函数
- * 采用 Parse 标准安全实践:
- * Parse Server 默认使用 bcrypt 对密码进行安全哈希存储。
- * 客户端/服务端传输应使用 HTTPS 保证安全。
- */
- import crypto from 'crypto';
- import fs from 'fs';
- console.log('Loading user.service.js...');
- function getLoginPrivateKey() {
- const keyPath = process.env.LOGIN_RSA_PRIVATE_KEY_FILE;
- if (!keyPath) throw new Error('LOGIN_RSA_PRIVATE_KEY_FILE is not configured');
- return fs.readFileSync(keyPath, 'utf8');
- }
- /**
- * 解密 RSA 加密的数据
- * @param {string} encryptedData Base64 编码的加密字符串
- * @returns {string} 解密后的明文字符串
- */
- function decryptRSA(encryptedData) {
- try {
- const buffer = Buffer.from(encryptedData, 'base64');
- const decrypted = crypto.privateDecrypt(
- {
- key: getLoginPrivateKey(),
- // 根据前端使用的 padding 方式进行调整,常见的是 crypto.constants.RSA_PKCS1_PADDING 或 RSA_PKCS1_OAEP_PADDING
- padding: crypto.constants.RSA_PKCS1_PADDING,
- },
- buffer
- );
- return decrypted.toString('utf8');
- } catch (error) {
- console.error('RSA Decryption failed:', error.message);
- throw new Error('解密失败');
- }
- }
- /**
- * 用户登录云函数
- * 调用方式: Parse.Cloud.run('user_login', { username, password })
- * 此时传入的 username 和 password 为 RSA 加密并经过 Base64 编码的字符串
- */
- Parse.Cloud.define('user_login', async request => {
- console.log('Cloud Function called: user_login');
- const { username: encryptedUsername, password: encryptedPassword } = request.params;
- // 参数校验
- if (!encryptedUsername || !encryptedPassword) {
- throw new Parse.Error(Parse.Error.VALIDATION_ERROR, '用户名和密码不能为空');
- }
- let username, password;
- try {
- // 解密账号和密码
- username = decryptRSA(encryptedUsername);
- password = decryptRSA(encryptedPassword);
- } catch (error) {
- throw new Parse.Error(Parse.Error.VALIDATION_ERROR, '账号或密码解密失败,请检查加密格式');
- }
- try {
- // 使用 Parse 原生登录,自动验证密码哈希
- // logIn 返回的用户对象已包含 sessionToken
- const user = await Parse.User.logIn(username, password);
-
- return {
- success: true,
- user: user.toJSON(),
- sessionToken: user.getSessionToken()
- };
- } catch (error) {
- console.error('Login error:', error);
- throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, '用户名或密码错误');
- }
- });
- /**
- * 用户注册云函数
- * 调用方式: Parse.Cloud.run('user_signup', { username, password, email, ...attributes })
- */
- Parse.Cloud.define('user_signup', async request => {
- if (!request.master) {
- throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, '公开注册已禁用');
- }
- console.log('Cloud Function called: user_signup');
- const { username, password, email, ...attributes } = request.params;
- // 参数校验
- if (!username || !password) {
- throw new Parse.Error(Parse.Error.VALIDATION_ERROR, '用户名和密码不能为空');
- }
- const user = new Parse.User();
- user.set('username', username);
- user.set('password', password); // Parse 会自动进行 bcrypt 加密存储
-
- if (email) {
- user.set('email', email);
- }
- // 动态设置其他属性
- Object.keys(attributes).forEach(key => {
- user.set(key, attributes[key]);
- });
- try {
- await user.signUp();
- return {
- success: true,
- userId: user.id,
- sessionToken: user.getSessionToken(),
- user: user.toJSON()
- };
- } catch (error) {
- console.error('Signup error:', error);
- // 转换错误信息(如用户名已存在)
- throw new Parse.Error(Parse.Error.USERNAME_TAKEN, error.message);
- }
- });
- export default {};
|