LingAdmin/Backend/Services/IdentityService/LingAdmin.IdentityService/Controllers/AuthController.cs

233 lines
6.7 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using LingAdmin.IdentityService.Services;
using LingAdmin.Shared.DTOs;
using System.Security.Claims;
namespace LingAdmin.IdentityService.Controllers;
/// <summary>
/// 认证控制器 - 处理用户注册、登录、令牌刷新等
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly IAuthService _authService;
private readonly ILogger<AuthController> _logger;
public AuthController(IAuthService authService, ILogger<AuthController> logger)
{
_authService = authService;
_logger = logger;
}
/// <summary>
/// 用户注册
/// </summary>
[HttpPost("register")]
public async Task<ActionResult<ApiResponse<UserDto>>> Register([FromBody] RegisterRequest request)
{
var (user, error) = await _authService.RegisterAsync(request);
if (error != null)
{
return BadRequest(ApiResponse<UserDto>.Error(error));
}
var userDto = new UserDto
{
Id = user!.Id,
Name = user.Name,
Email = user.Email,
Status = user.Status,
CreatedAt = user.CreatedAt
};
return CreatedAtAction(nameof(GetProfile), null, ApiResponse<UserDto>.Created(userDto, "Registration successful"));
}
/// <summary>
/// 用户登录
/// </summary>
[HttpPost("login")]
public async Task<ActionResult<ApiResponse<LoginResponse>>> Login([FromBody] LoginRequest request)
{
var ipAddress = GetIpAddress();
var (response, error) = await _authService.LoginAsync(request, ipAddress);
if (error != null)
{
return Unauthorized(ApiResponse<LoginResponse>.Unauthorized(error));
}
SetRefreshTokenCookie(response!.RefreshToken);
return Ok(ApiResponse<LoginResponse>.Ok(response, "Login successful"));
}
/// <summary>
/// 刷新访问令牌
/// </summary>
[HttpPost("refresh-token")]
public async Task<ActionResult<ApiResponse<TokenRefreshResponse>>> RefreshToken([FromBody] RefreshTokenRequest? request = null)
{
var refreshToken = request?.RefreshToken ?? Request.Cookies["refreshToken"];
if (string.IsNullOrEmpty(refreshToken))
{
return BadRequest(ApiResponse<TokenRefreshResponse>.Error("Refresh token is required"));
}
var ipAddress = GetIpAddress();
var (response, error) = await _authService.RefreshTokenAsync(refreshToken, ipAddress);
if (error != null)
{
return Unauthorized(ApiResponse<TokenRefreshResponse>.Unauthorized(error));
}
SetRefreshTokenCookie(response!.RefreshToken);
return Ok(ApiResponse<TokenRefreshResponse>.Ok(response));
}
/// <summary>
/// 登出(撤销刷新令牌)
/// </summary>
[HttpPost("logout")]
public async Task<ActionResult<ApiResponse<object>>> Logout([FromBody] RefreshTokenRequest? request = null)
{
var refreshToken = request?.RefreshToken ?? Request.Cookies["refreshToken"];
if (string.IsNullOrEmpty(refreshToken))
{
return BadRequest(ApiResponse<object>.Error("Refresh token is required"));
}
var ipAddress = GetIpAddress();
var result = await _authService.RevokeTokenAsync(refreshToken, ipAddress);
if (!result)
{
return NotFound(ApiResponse<object>.NotFound("Token not found or already revoked"));
}
// Clear the refresh token cookie
Response.Cookies.Delete("refreshToken");
return Ok(ApiResponse<object>.Ok(new { }, "Logout successful"));
}
/// <summary>
/// 修改密码
/// </summary>
[Authorize]
[HttpPost("change-password")]
public async Task<ActionResult<ApiResponse<object>>> ChangePassword([FromBody] ChangePasswordRequest request)
{
var userId = GetCurrentUserId();
if (userId == null)
{
return Unauthorized(ApiResponse<object>.Unauthorized());
}
var (success, error) = await _authService.ChangePasswordAsync(userId.Value, request);
if (!success)
{
return BadRequest(ApiResponse<object>.Error(error!));
}
// Clear refresh token cookie after password change
Response.Cookies.Delete("refreshToken");
return Ok(ApiResponse<object>.Ok(new { }, "Password changed successfully"));
}
/// <summary>
/// 获取当前用户信息
/// </summary>
[Authorize]
[HttpGet("profile")]
public async Task<ActionResult<ApiResponse<UserDto>>> GetProfile()
{
var userId = GetCurrentUserId();
if (userId == null)
{
return Unauthorized(ApiResponse<UserDto>.Unauthorized());
}
var user = await _authService.GetUserByIdAsync(userId.Value);
if (user == null)
{
return NotFound(ApiResponse<UserDto>.NotFound("User not found"));
}
var userDto = new UserDto
{
Id = user.Id,
Name = user.Name,
Email = user.Email,
Status = user.Status,
CreatedAt = user.CreatedAt,
LastLoginAt = user.LastLoginAt
};
return Ok(ApiResponse<UserDto>.Ok(userDto));
}
/// <summary>
/// 验证令牌是否有效
/// </summary>
[Authorize]
[HttpGet("validate")]
public ActionResult<ApiResponse<object>> ValidateToken()
{
var userId = GetCurrentUserId();
var email = User.FindFirst(ClaimTypes.Email)?.Value;
var roles = User.FindAll(ClaimTypes.Role).Select(c => c.Value).ToList();
return Ok(ApiResponse<object>.Ok(new
{
UserId = userId,
Email = email,
Roles = roles,
IsValid = true
}));
}
#region Private Helpers
private int? GetCurrentUserId()
{
var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (int.TryParse(userIdClaim, out var userId))
{
return userId;
}
return null;
}
private string? GetIpAddress()
{
if (Request.Headers.ContainsKey("X-Forwarded-For"))
{
return Request.Headers["X-Forwarded-For"].FirstOrDefault();
}
return HttpContext.Connection.RemoteIpAddress?.MapToIPv4().ToString();
}
private void SetRefreshTokenCookie(string token)
{
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Expires = DateTime.UtcNow.AddDays(7),
SameSite = SameSiteMode.Strict,
Secure = true
};
Response.Cookies.Append("refreshToken", token, cookieOptions);
}
#endregion
}