using Microsoft.AspNetCore.Mvc;
using MediatR;
using CellularManagement.Application.Features.Auth.Commands.AuthenticateUser;
using CellularManagement.Application.Features.Auth.Commands.RegisterUser;
using CellularManagement.Application.Features.Auth.Commands.RefreshToken;
using CellularManagement.Application.Common;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Services;
using Microsoft.Extensions.Caching.Memory;
using CellularManagement.Infrastructure.Configurations;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Http;
using CellularManagement.Presentation.Abstractions;
using CellularManagement.Application.Features.Auth.Commands.Login;
using Swashbuckle.AspNetCore.Filters;
using CellularManagement.Domain.Common;
namespace CellularManagement.Presentation.Controllers;
///
/// 认证控制器
/// 提供用户认证相关的 API 接口,包括登录和注册功能
///
public class AuthController : ApiController
{
private readonly ILogger _logger;
private readonly ICacheService _cache;
private readonly AuthConfiguration _authConfig;
///
/// 初始化认证控制器
///
/// MediatR 中介者,用于处理命令和查询
/// 日志记录器
/// 缓存服务
/// 认证配置
public AuthController(
IMediator mediator,
ILogger logger,
ICacheService cache,
IOptions authConfig) : base(mediator)
{
_logger = logger;
_cache = cache;
_authConfig = authConfig.Value;
}
///
/// 用户登录
///
///
/// 示例请求:
///
/// POST /api/auth/login
/// {
/// "userNameOrEmail": "用户名或邮箱",
/// "password": "密码"
/// }
///
///
/// 登录命令,包含用户名/邮箱和密码
///
/// 登录结果,包含:
/// - 成功:返回用户信息和访问令牌
/// - 失败:返回错误信息
///
/// 登录成功,返回用户信息和令牌
/// 登录失败,返回错误信息
/// 登录尝试次数过多
[HttpPost()]
[SwaggerRequestExample(typeof(LoginRequest), typeof(LoginRequestExample))]
[ProducesResponseType(typeof(OperationResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult), StatusCodes.Status429TooManyRequests)]
public async Task>> Login([FromBody] AuthenticateUserCommand command)
{
try
{
// 检查登录尝试次数
var cacheKey = string.Format(_authConfig.LoginAttemptsCacheKeyFormat, command.UserName);
var attempts = _cache.Get(cacheKey);
if (attempts >= _authConfig.MaxLoginAttempts)
{
_logger.LogWarning("用户 {UserName} 登录尝试次数过多", command.UserName);
return StatusCode(StatusCodes.Status429TooManyRequests,
OperationResult.CreateFailure("登录尝试次数过多,请稍后再试"));
}
// 执行登录
var result = await mediator.Send(command);
if (!result.IsSuccess)
{
// 增加登录尝试次数
var options = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(_authConfig.LoginAttemptsWindowMinutes));
_cache.Set(cacheKey, attempts + 1, options);
_logger.LogWarning("用户 {UserName} 登录失败: {Error}",
command.UserName,
result.ErrorMessages?.FirstOrDefault());
}
else
{
// 清除登录尝试次数
_cache.Remove(cacheKey);
_logger.LogInformation("用户 {UserName} 登录成功", command.UserName);
}
_logger.LogWarning($"Bearer {result.Data.AccessToken}");
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "用户 {UserName} 登录时发生异常", command.UserName);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult.CreateFailure("系统错误,请稍后重试"));
}
}
///
/// 用户注册
///
///
/// 示例请求:
///
/// POST /api/auth/register
/// {
/// "userName": "用户名",
/// "email": "邮箱",
/// "password": "密码",
/// "confirmPassword": "确认密码",
/// "phoneNumber": "手机号"
/// }
///
///
/// 注册命令,包含用户注册信息
///
/// 注册结果,包含:
/// - 成功:返回用户ID
/// - 失败:返回错误信息
///
/// 注册成功,返回用户ID
/// 注册失败,返回错误信息
[HttpPost()]
[ProducesResponseType(typeof(OperationResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult), StatusCodes.Status400BadRequest)]
public async Task>> Register([FromBody] RegisterUserCommand command)
{
try
{
// 执行注册
var result = await mediator.Send(command);
if (result.IsSuccess)
{
_logger.LogInformation("用户 {UserName} 注册成功", command.UserName);
}
else
{
_logger.LogWarning("用户 {UserName} 注册失败: {Error}",
command.UserName,
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "用户 {UserName} 注册时发生异常", command.UserName);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult.CreateFailure("系统错误,请稍后重试"));
}
}
///
/// 刷新令牌
///
///
/// 示例请求:
///
/// POST /api/auth/refresh-token
/// {
/// "refreshToken": "刷新令牌"
/// }
///
///
/// 刷新令牌命令
///
/// 刷新结果,包含:
/// - 成功:返回用户信息和新的访问令牌
/// - 失败:返回错误信息
///
/// 刷新成功,返回用户信息和新的令牌
/// 刷新失败,返回错误信息
[HttpPost()]
[ProducesResponseType(typeof(OperationResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult), StatusCodes.Status400BadRequest)]
public async Task>> RefreshToken([FromBody] RefreshTokenCommand command)
{
try
{
var result = await mediator.Send(command);
if (result.IsSuccess)
{
_logger.LogInformation("令牌刷新成功");
}
else
{
_logger.LogWarning("令牌刷新失败: {Error}",
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "刷新令牌时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult.CreateFailure("系统错误,请稍后重试"));
}
}
}