168 lines
6.6 KiB
C#
168 lines
6.6 KiB
C#
using FutureMailAPI.Helpers;
|
||
using FutureMailAPI.DTOs;
|
||
using System.Security.Claims;
|
||
|
||
namespace FutureMailAPI.Services
|
||
{
|
||
public interface IAuthService
|
||
{
|
||
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;
|
||
|
||
public AuthService(
|
||
IUserService userService,
|
||
IPasswordHelper passwordHelper,
|
||
IOAuthService oauthService)
|
||
{
|
||
_userService = userService;
|
||
_passwordHelper = passwordHelper;
|
||
_oauthService = oauthService;
|
||
}
|
||
|
||
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("获取用户信息失败");
|
||
}
|
||
|
||
var user = userResult.Data;
|
||
|
||
// 创建用户响应DTO
|
||
var userResponse = new UserResponseDto
|
||
{
|
||
Id = user.Id,
|
||
Username = user.Username,
|
||
Email = user.Email,
|
||
Nickname = user.Nickname,
|
||
Avatar = user.Avatar,
|
||
CreatedAt = user.CreatedAt,
|
||
LastLoginAt = DateTime.UtcNow
|
||
};
|
||
|
||
// 创建认证响应DTO,使用OAuth令牌
|
||
var authResponse = new AuthResponseDto
|
||
{
|
||
Token = oauthResult.Data.AccessToken,
|
||
RefreshToken = oauthResult.Data.RefreshToken,
|
||
Expires = DateTime.UtcNow.AddSeconds(oauthResult.Data.ExpiresIn),
|
||
User = userResponse
|
||
};
|
||
|
||
return ApiResponse<AuthResponseDto>.SuccessResult(authResponse, "登录成功");
|
||
}
|
||
|
||
public async Task<ApiResponse<AuthResponseDto>> RegisterAsync(UserRegisterDto registerDto)
|
||
{
|
||
// 检查用户名是否已存在
|
||
var existingUserResult = await _userService.GetUserByUsernameAsync(registerDto.Username);
|
||
|
||
if (existingUserResult.Success && existingUserResult.Data != null)
|
||
{
|
||
return ApiResponse<AuthResponseDto>.ErrorResult("用户名已存在");
|
||
}
|
||
|
||
// 检查邮箱是否已存在
|
||
var existingEmailResult = await _userService.GetUserByEmailAsync(registerDto.Email);
|
||
|
||
if (existingEmailResult.Success && existingEmailResult.Data != null)
|
||
{
|
||
return ApiResponse<AuthResponseDto>.ErrorResult("邮箱已被注册");
|
||
}
|
||
|
||
// 创建用户
|
||
var createUserResult = await _userService.CreateUserAsync(registerDto);
|
||
|
||
if (!createUserResult.Success)
|
||
{
|
||
return ApiResponse<AuthResponseDto>.ErrorResult(createUserResult.Message ?? "注册失败");
|
||
}
|
||
|
||
// 注册成功后,自动使用OAuth登录
|
||
var loginDto = new UserLoginDto
|
||
{
|
||
UsernameOrEmail = registerDto.Username,
|
||
Password = registerDto.Password
|
||
};
|
||
|
||
return await LoginAsync(loginDto);
|
||
}
|
||
|
||
public async Task<ApiResponse<bool>> ValidateTokenAsync(string token)
|
||
{
|
||
// 注意:在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
|
||
{
|
||
ClientId = defaultClientId,
|
||
ClientSecret = defaultClientSecret,
|
||
RefreshToken = token,
|
||
GrantType = "refresh_token",
|
||
Scope = "read write"
|
||
};
|
||
|
||
// 使用OAuth服务刷新令牌
|
||
var oauthResult = await _oauthService.RefreshTokenAsync(oauthTokenRequest);
|
||
|
||
if (!oauthResult.Success)
|
||
{
|
||
return ApiResponse<string>.ErrorResult(oauthResult.Message ?? "刷新令牌失败");
|
||
}
|
||
|
||
// 返回新的访问令牌
|
||
return ApiResponse<string>.SuccessResult(oauthResult.Data.AccessToken, "令牌刷新成功");
|
||
}
|
||
}
|
||
} |