295 lines
10 KiB
C#
295 lines
10 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using FutureMailAPI.Services;
|
|
using FutureMailAPI.DTOs;
|
|
using FutureMailAPI.Models;
|
|
using FutureMailAPI.Extensions;
|
|
|
|
namespace FutureMailAPI.Controllers
|
|
{
|
|
[ApiController]
|
|
[Route("api/v1/oauth")]
|
|
public class OAuthController : ControllerBase
|
|
{
|
|
private readonly IOAuthService _oauthService;
|
|
private readonly ILogger<OAuthController> _logger;
|
|
|
|
public OAuthController(IOAuthService oauthService, ILogger<OAuthController> logger)
|
|
{
|
|
_oauthService = oauthService;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// OAuth登录端点
|
|
/// </summary>
|
|
[HttpPost("login")]
|
|
public async Task<IActionResult> Login([FromBody] OAuthLoginDto loginDto)
|
|
{
|
|
try
|
|
{
|
|
var result = await _oauthService.LoginAsync(loginDto);
|
|
|
|
if (result.Success)
|
|
{
|
|
return Ok(result);
|
|
}
|
|
|
|
return BadRequest(result);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "OAuth登录时发生错误");
|
|
return StatusCode(500, new { message = "服务器内部错误" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建OAuth客户端
|
|
/// </summary>
|
|
[HttpPost("clients")]
|
|
public async Task<IActionResult> CreateClient([FromBody] OAuthClientCreateDto createDto)
|
|
{
|
|
try
|
|
{
|
|
// 从OAuth中间件获取当前用户ID
|
|
var userId = HttpContext.GetCurrentUserId();
|
|
if (!userId.HasValue)
|
|
{
|
|
return Unauthorized(new { message = "未授权访问" });
|
|
}
|
|
|
|
var result = await _oauthService.CreateClientAsync(userId.Value, createDto);
|
|
|
|
if (result.Success)
|
|
{
|
|
return Ok(result);
|
|
}
|
|
|
|
return BadRequest(result);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "创建OAuth客户端时发生错误");
|
|
return StatusCode(500, new { message = "服务器内部错误" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取OAuth客户端信息
|
|
/// </summary>
|
|
[HttpGet("clients/{clientId}")]
|
|
public async Task<IActionResult> GetClient(string clientId)
|
|
{
|
|
try
|
|
{
|
|
var result = await _oauthService.GetClientAsync(clientId);
|
|
|
|
if (result.Success)
|
|
{
|
|
return Ok(result);
|
|
}
|
|
|
|
return NotFound(result);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "获取OAuth客户端信息时发生错误");
|
|
return StatusCode(500, new { message = "服务器内部错误" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// OAuth授权端点
|
|
/// </summary>
|
|
[HttpGet("authorize")]
|
|
public async Task<IActionResult> Authorize([FromQuery] OAuthAuthorizationRequestDto request)
|
|
{
|
|
try
|
|
{
|
|
// 从OAuth中间件获取当前用户ID
|
|
var userId = HttpContext.GetCurrentUserId();
|
|
if (!userId.HasValue)
|
|
{
|
|
// 如果用户未登录,重定向到登录页面
|
|
var loginRedirectUri = $"/api/v1/auth/login?redirect_uri={Uri.EscapeDataString(request.RedirectUri)}";
|
|
if (!string.IsNullOrEmpty(request.State))
|
|
{
|
|
loginRedirectUri += $"&state={request.State}";
|
|
}
|
|
return Redirect(loginRedirectUri);
|
|
}
|
|
|
|
var result = await _oauthService.AuthorizeAsync(userId.Value, request);
|
|
|
|
if (result.Success)
|
|
{
|
|
// 重定向到客户端,携带授权码
|
|
var redirectUri = $"{request.RedirectUri}?code={result.Data.Code}";
|
|
if (!string.IsNullOrEmpty(request.State))
|
|
{
|
|
redirectUri += $"&state={request.State}";
|
|
}
|
|
|
|
return Redirect(redirectUri);
|
|
}
|
|
|
|
// 错误重定向
|
|
var errorRedirectUri = $"{request.RedirectUri}?error={result.Message}";
|
|
if (!string.IsNullOrEmpty(request.State))
|
|
{
|
|
errorRedirectUri += $"&state={request.State}";
|
|
}
|
|
|
|
return Redirect(errorRedirectUri);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "OAuth授权时发生错误");
|
|
|
|
// 错误重定向
|
|
var errorRedirectUri = $"{request.RedirectUri}?error=server_error";
|
|
if (!string.IsNullOrEmpty(request.State))
|
|
{
|
|
errorRedirectUri += $"&state={request.State}";
|
|
}
|
|
|
|
return Redirect(errorRedirectUri);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// OAuth令牌端点
|
|
/// </summary>
|
|
[HttpPost("token")]
|
|
[Microsoft.AspNetCore.Authorization.AllowAnonymous]
|
|
public async Task<IActionResult> ExchangeToken([FromForm] OAuthTokenRequestDto request)
|
|
{
|
|
_logger.LogInformation("OAuth令牌端点被调用");
|
|
|
|
try
|
|
{
|
|
_logger.LogInformation("OAuth令牌交换请求: GrantType={GrantType}, ClientId={ClientId}, Username={Username}",
|
|
request.GrantType, request.ClientId, request.Username);
|
|
|
|
if (request.GrantType == "authorization_code")
|
|
{
|
|
var result = await _oauthService.ExchangeCodeForTokenAsync(request);
|
|
|
|
if (result.Success)
|
|
{
|
|
return Ok(result);
|
|
}
|
|
|
|
return BadRequest(result);
|
|
}
|
|
else if (request.GrantType == "refresh_token")
|
|
{
|
|
var result = await _oauthService.RefreshTokenAsync(request);
|
|
|
|
if (result.Success)
|
|
{
|
|
return Ok(result);
|
|
}
|
|
|
|
return BadRequest(result);
|
|
}
|
|
else if (request.GrantType == "password")
|
|
{
|
|
_logger.LogInformation("处理密码授权类型登录请求");
|
|
|
|
// 创建OAuth登录请求
|
|
var loginDto = new OAuthLoginDto
|
|
{
|
|
UsernameOrEmail = request.Username,
|
|
Password = request.Password,
|
|
ClientId = request.ClientId,
|
|
ClientSecret = request.ClientSecret,
|
|
Scope = request.Scope
|
|
};
|
|
|
|
var result = await _oauthService.LoginAsync(loginDto);
|
|
|
|
if (result.Success)
|
|
{
|
|
_logger.LogInformation("密码授权类型登录成功");
|
|
return Ok(result);
|
|
}
|
|
|
|
_logger.LogWarning("密码授权类型登录失败: {Message}", result.Message);
|
|
return BadRequest(result);
|
|
}
|
|
else
|
|
{
|
|
_logger.LogWarning("不支持的授权类型: {GrantType}", request.GrantType);
|
|
return BadRequest(new { message = "不支持的授权类型" });
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "OAuth令牌交换时发生错误");
|
|
return StatusCode(500, new { message = "服务器内部错误" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 撤销令牌
|
|
/// </summary>
|
|
[HttpPost("revoke")]
|
|
public async Task<IActionResult> RevokeToken([FromForm] string token, [FromForm] string token_type_hint = "access_token")
|
|
{
|
|
try
|
|
{
|
|
var result = await _oauthService.RevokeTokenAsync(token);
|
|
|
|
if (result.Success)
|
|
{
|
|
return Ok(new { message = "令牌已撤销" });
|
|
}
|
|
|
|
return BadRequest(result);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "撤销令牌时发生错误");
|
|
return StatusCode(500, new { message = "服务器内部错误" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 验证令牌
|
|
/// </summary>
|
|
[HttpPost("introspect")]
|
|
public async Task<IActionResult> IntrospectToken([FromForm] string token)
|
|
{
|
|
try
|
|
{
|
|
var result = await _oauthService.ValidateTokenAsync(token);
|
|
|
|
if (result.Success)
|
|
{
|
|
var accessToken = await _oauthService.GetAccessTokenAsync(token);
|
|
|
|
if (accessToken != null)
|
|
{
|
|
return Ok(new
|
|
{
|
|
active = true,
|
|
scope = accessToken.Scopes,
|
|
client_id = accessToken.Client.ClientId,
|
|
username = accessToken.User.Email,
|
|
exp = ((DateTimeOffset)accessToken.ExpiresAt).ToUnixTimeSeconds(),
|
|
iat = ((DateTimeOffset)accessToken.CreatedAt).ToUnixTimeSeconds()
|
|
});
|
|
}
|
|
}
|
|
|
|
return Ok(new { active = false });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "验证令牌时发生错误");
|
|
return StatusCode(500, new { message = "服务器内部错误" });
|
|
}
|
|
}
|
|
}
|
|
} |