修改接口

This commit is contained in:
2025-10-16 15:21:52 +08:00
parent 82220ce0b8
commit dd398c1c32
274 changed files with 22777 additions and 22905 deletions

View File

@@ -1,6 +1,13 @@
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
{
@@ -8,86 +15,73 @@ namespace FutureMailAPI.Services
{
Task<ApiResponse<AuthResponseDto>> LoginAsync(UserLoginDto loginDto);
Task<ApiResponse<AuthResponseDto>> RegisterAsync(UserRegisterDto registerDto);
Task<ApiResponse<bool>> ValidateTokenAsync(string token);
Task<ApiResponse<string>> RefreshTokenAsync(string token);
Task<ApiResponse<AuthResponseDto>> LoginWithOAuthAsync(UserLoginDto loginDto, string clientId, string clientSecret);
}
public class AuthService : IAuthService
{
private readonly IUserService _userService;
private readonly IPasswordHelper _passwordHelper;
private readonly IOAuthService _oauthService;
private readonly FutureMailDbContext _context;
private readonly IConfiguration _configuration;
public AuthService(
IUserService userService,
IPasswordHelper passwordHelper,
IOAuthService oauthService)
FutureMailDbContext context,
IConfiguration configuration)
{
_userService = userService;
_passwordHelper = passwordHelper;
_oauthService = oauthService;
_context = context;
_configuration = configuration;
}
public async Task<ApiResponse<AuthResponseDto>> LoginAsync(UserLoginDto loginDto)
{
// 使用默认客户端ID和密钥进行OAuth登录
// 在实际应用中,这些应该从配置中获取
var defaultClientId = "futuremail_default_client";
var defaultClientSecret = "futuremail_default_secret";
return await LoginWithOAuthAsync(loginDto, defaultClientId, defaultClientSecret);
}
public async Task<ApiResponse<AuthResponseDto>> LoginWithOAuthAsync(UserLoginDto loginDto, string clientId, string clientSecret)
{
// 创建OAuth登录请求
var oauthLoginDto = new OAuthLoginDto
{
UsernameOrEmail = loginDto.UsernameOrEmail,
Password = loginDto.Password,
ClientId = clientId,
ClientSecret = clientSecret,
Scope = "read write" // 默认权限范围
};
// 使用OAuth服务进行登录
var oauthResult = await _oauthService.LoginAsync(oauthLoginDto);
if (!oauthResult.Success)
{
return ApiResponse<AuthResponseDto>.ErrorResult(oauthResult.Message ?? "登录失败");
}
// 获取用户信息
var userResult = await _userService.GetUserByUsernameOrEmailAsync(loginDto.UsernameOrEmail);
if (!userResult.Success || userResult.Data == null)
{
return ApiResponse<AuthResponseDto>.ErrorResult("获取用户信息失败");
return ApiResponse<AuthResponseDto>.ErrorResult("用户名或密码错误");
}
var user = userResult.Data;
var userDto = userResult.Data;
// 创建用户响应DTO
var userResponse = new UserResponseDto
// 获取原始用户信息用于密码验证
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Id == userDto.Id);
if (user == null)
{
Id = user.Id,
Username = user.Username,
Email = user.Email,
Nickname = user.Nickname,
Avatar = user.Avatar,
CreatedAt = user.CreatedAt,
LastLoginAt = DateTime.UtcNow
};
return ApiResponse<AuthResponseDto>.ErrorResult("用户不存在");
}
// 创建认证响应DTO使用OAuth令牌
// 验证密码
if (!_passwordHelper.VerifyPassword(loginDto.Password, user.PasswordHash, user.Salt))
{
return ApiResponse<AuthResponseDto>.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
{
Token = oauthResult.Data.AccessToken,
RefreshToken = oauthResult.Data.RefreshToken,
Expires = DateTime.UtcNow.AddSeconds(oauthResult.Data.ExpiresIn),
User = userResponse
User = userDto,
Token = token,
RefreshToken = refreshToken,
ExpiresIn = 3600 // 1小时单位秒
};
return ApiResponse<AuthResponseDto>.SuccessResult(authResponse, "登录成功");
@@ -119,7 +113,7 @@ namespace FutureMailAPI.Services
return ApiResponse<AuthResponseDto>.ErrorResult(createUserResult.Message ?? "注册失败");
}
// 注册成功后,自动使用OAuth登录
// 注册成功后,自动登录
var loginDto = new UserLoginDto
{
UsernameOrEmail = registerDto.Username,
@@ -129,40 +123,35 @@ namespace FutureMailAPI.Services
return await LoginAsync(loginDto);
}
public async Task<ApiResponse<bool>> ValidateTokenAsync(string token)
private string GenerateJwtToken(User user)
{
// 注意在OAuth 2.0中令牌验证应该由OAuth中间件处理
// 这里我们暂时返回成功实际使用时应该通过OAuth 2.0的令牌验证流程
return ApiResponse<bool>.SuccessResult(true);
}
public async Task<ApiResponse<string>> RefreshTokenAsync(string token)
{
// 在OAuth 2.0中刷新令牌需要客户端ID和密钥
// 这里我们使用默认客户端凭据
var defaultClientId = "futuremail_default_client";
var defaultClientSecret = "futuremail_default_secret";
// 创建OAuth刷新令牌请求
var oauthTokenRequest = new OAuthTokenRequestDto
var jwtSettings = _configuration.GetSection("Jwt");
var key = Encoding.ASCII.GetBytes(jwtSettings["Key"] ?? throw new InvalidOperationException("JWT密钥未配置"));
var tokenDescriptor = new SecurityTokenDescriptor
{
ClientId = defaultClientId,
ClientSecret = defaultClientSecret,
RefreshToken = token,
GrantType = "refresh_token",
Scope = "read write"
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)
};
// 使用OAuth服务刷新令牌
var oauthResult = await _oauthService.RefreshTokenAsync(oauthTokenRequest);
if (!oauthResult.Success)
{
return ApiResponse<string>.ErrorResult(oauthResult.Message ?? "刷新令牌失败");
}
// 返回新的访问令牌
return ApiResponse<string>.SuccessResult(oauthResult.Data.AccessToken, "令牌刷新成功");
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);
}
}
}