using BCrypt.Net; using iFileProxy.Models; using System.Security.Claims; using System.IdentityModel.Tokens.Jwt; using Microsoft.IdentityModel.Tokens; using System.Text; namespace iFileProxy.Services { public class AuthService { private readonly DatabaseGateService _dbGateService; private readonly IConfiguration _configuration; private readonly ILogger _logger; public AuthService(DatabaseGateService dbGateService, IConfiguration configuration, ILogger logger) { _dbGateService = dbGateService; _configuration = configuration; _logger = logger; } public async Task<(bool success, string message)> RegisterAsync(RegisterRequest request, string ipAddr) { try { // 检查用户名是否已存在 if (await _dbGateService.UserExistsAsync(request.Username, request.Email)) { return (false, "用户名或电子邮件已存在"); } // 检查是否是第一个用户 var isFirstUser = await _dbGateService.GetUserCountAsync() == 0; // 创建新用户 var user = new User { Username = request.Username, PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password), LastLoginIP = ipAddr, // 如果是第一个用户,设置为超级管理员 Mask = isFirstUser ? UserMask.SuperAdmin : UserMask.User, Nickname = request.NickName, Email = request.Email, }; // 保存用户 await _dbGateService.CreateUserAsync(user); // 记录注册事件 var userEvent = new UserEvent { UserId = user.UserId, EventType = UserEventType.Registry, EventIP = ipAddr, EventDetail = isFirstUser ? "超级管理员注册" : "用户注册" }; await _dbGateService.CreateUserEventAsync(userEvent); return (true, isFirstUser ? "超级管理员注册成功" : "注册成功"); } catch (Exception ex) { _logger.LogError(ex, "用户注册失败"); return (false, "注册失败"); } } public async Task<(bool success, string token, string message)> LoginAsync(string account, string password, string ip, string userAgent, string fingerprint) { try { var user = await _dbGateService.GetUserByAccountAsync(account); if (user == null) { return (false, string.Empty, "用户不存在"); } if (user.State == UserState.Blocked) { return (false, string.Empty, "账户已被封禁"); } if (!BCrypt.Net.BCrypt.Verify(password, user.PasswordHash)) { return (false, string.Empty, "密码错误"); } // 更新登录信息 user.LastLoginTime = DateTime.Now; user.LastLoginIP = ip; await _dbGateService.UpdateUserAsync(user); // 记录登录事件 var userEvent = new UserEvent { UserId = user.UserId, EventType = UserEventType.Login, EventIP = ip, EventDetail = $"用户通过{(account.Contains('@') ? "邮箱" : "用户名")}登录" }; await _dbGateService.CreateUserEventAsync(userEvent); // 生成包含客户端信息的token var token = GenerateJwtToken(user, new ClientInfo { IP = ip, UserAgent = userAgent, Fingerprint = fingerprint }); return (true, token, "登录成功"); } catch (Exception ex) { _logger.LogError(ex, "用户登录失败"); return (false, string.Empty, "登录失败"); } } private string GenerateJwtToken(User user, ClientInfo clientInfo) { var claims = new[] { new Claim(ClaimTypes.NameIdentifier, user.UserId), new Claim(ClaimTypes.Name, user.Username), new Claim(ClaimTypes.Role, user.Mask.ToString()), new Claim("ip", clientInfo.IP), new Claim("userAgent", clientInfo.UserAgent), new Claim("fingerprint", clientInfo.Fingerprint) }; // 确保密钥至少32字节长 var key = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(_configuration["Jwt:Key"] ?? "iFileProxy-JWT-Secret-Key-2024-Very-Long-Secret-Key-For-Security")); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: _configuration["Jwt:Issuer"] ?? "iFileProxy", audience: _configuration["Jwt:Audience"] ?? "iFileProxy.Client", claims: claims, expires: DateTime.Now.AddDays(1), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } } }