using FutureMailAPI.Helpers; using FutureMailAPI.DTOs; using FutureMailAPI.Models; using FutureMailAPI.Data; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using System.Text; namespace FutureMailAPI.Services { public interface IAuthService { Task> LoginAsync(UserLoginDto loginDto); Task> RegisterAsync(UserRegisterDto registerDto); } public class AuthService : IAuthService { private readonly IUserService _userService; private readonly IPasswordHelper _passwordHelper; private readonly FutureMailDbContext _context; private readonly IConfiguration _configuration; public AuthService( IUserService userService, IPasswordHelper passwordHelper, FutureMailDbContext context, IConfiguration configuration) { _userService = userService; _passwordHelper = passwordHelper; _context = context; _configuration = configuration; } public async Task> LoginAsync(UserLoginDto loginDto) { // 获取用户信息 var userResult = await _userService.GetUserByUsernameOrEmailAsync(loginDto.UsernameOrEmail); if (!userResult.Success || userResult.Data == null) { return ApiResponse.ErrorResult("用户名或密码错误"); } var userDto = userResult.Data; // 获取原始用户信息用于密码验证 var user = await _context.Users .FirstOrDefaultAsync(u => u.Id == userDto.Id); if (user == null) { return ApiResponse.ErrorResult("用户不存在"); } // 验证密码 if (!_passwordHelper.VerifyPassword(loginDto.Password, user.PasswordHash, user.Salt)) { return ApiResponse.ErrorResult("用户名或密码错误"); } // 更新用户响应DTO userDto.LastLoginAt = DateTime.UtcNow; // 生成JWT令牌 var token = GenerateJwtToken(user); var refreshToken = GenerateRefreshToken(); // 保存刷新令牌到用户表 user.RefreshToken = refreshToken; user.RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(7); // 刷新令牌7天过期 await _context.SaveChangesAsync(); // 创建认证响应DTO var authResponse = new AuthResponseDto { User = userDto, Token = token, RefreshToken = refreshToken, ExpiresIn = 3600 // 1小时,单位秒 }; return ApiResponse.SuccessResult(authResponse, "登录成功"); } public async Task> RegisterAsync(UserRegisterDto registerDto) { // 检查用户名是否已存在 var existingUserResult = await _userService.GetUserByUsernameAsync(registerDto.Username); if (existingUserResult.Success && existingUserResult.Data != null) { return ApiResponse.ErrorResult("用户名已存在"); } // 检查邮箱是否已存在 var existingEmailResult = await _userService.GetUserByEmailAsync(registerDto.Email); if (existingEmailResult.Success && existingEmailResult.Data != null) { return ApiResponse.ErrorResult("邮箱已被注册"); } // 创建用户 var createUserResult = await _userService.CreateUserAsync(registerDto); if (!createUserResult.Success) { return ApiResponse.ErrorResult(createUserResult.Message ?? "注册失败"); } // 注册成功后,自动登录 var loginDto = new UserLoginDto { UsernameOrEmail = registerDto.Username, Password = registerDto.Password }; return await LoginAsync(loginDto); } private string GenerateJwtToken(User user) { var jwtSettings = _configuration.GetSection("Jwt"); var key = Encoding.ASCII.GetBytes(jwtSettings["Key"] ?? throw new InvalidOperationException("JWT密钥未配置")); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), new Claim(ClaimTypes.Name, user.Username), new Claim(ClaimTypes.Email, user.Email) }), Expires = DateTime.UtcNow.AddHours(1), Issuer = jwtSettings["Issuer"], Audience = jwtSettings["Audience"], SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var tokenHandler = new JwtSecurityTokenHandler(); var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } private string GenerateRefreshToken() { var randomNumber = new byte[32]; using var rng = RandomNumberGenerator.Create(); rng.GetBytes(randomNumber); return Convert.ToBase64String(randomNumber); } } }