初始化
This commit is contained in:
		
							
								
								
									
										295
									
								
								FutureMailAPI/Controllers/OAuthController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								FutureMailAPI/Controllers/OAuthController.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,295 @@
 | 
			
		||||
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 = "服务器内部错误" });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user