Files
StoreWeb/Store.API/Controllers/AuthController.cs
T
2026-11-06 19:25:36 +08:00

116 lines
3.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Asp.Versioning;
using MAX.Framework.Dtos;
using MAX.Framework.Security;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Store.Users.Contracts;
namespace Store.Api.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class AuthController : ControllerBase
{
private readonly IUserAuthenticationService _users;
private readonly ITokenService _tokenService;
private readonly ICurrentUser _currentUser;
private readonly IOnlineUserStore _onlineUserStore;
private readonly ILogger<AuthController> _logger;
public AuthController(ITokenService tokenService, ICurrentUser currentUser, IOnlineUserStore onlineUserStore, ILogger<AuthController> logger, IUserAuthenticationService users)
{
_users = users;
_tokenService = tokenService;
_currentUser = currentUser;
_onlineUserStore = onlineUserStore;
_logger = logger;
}
/// <summary>
/// 登录:校验用户名/密码,签发数据库 Token(同账号支持多个独立会话)
/// </summary>
[HttpPost]
[EndpointSummary("用户登录")]
[AllowAnonymous]
public async Task<ApiResultBase> Login([FromBody] LoginRequest request)
{
_logger.LogInformation("login");
if (request is null || string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Password))
{
return ApiResult.Fail("用户名或密码不能为空", 400);
}
// 认证通过后才签发令牌,权限信息以用户模块中的数据库记录为准。
var user = await _users.Authenticate(request.UserName, request.Password, HttpContext.RequestAborted);
if (user is null) return ApiResult.Fail("用户名或密码错误", 401);
var claims = new List<Claim>
{
new(JwtClaimTypes.UserName, user.UserName),
};
if (request.DeviceId?.Length > 100 || request.DeviceName?.Length > 100)
return ApiResult.Fail("设备信息最多 100 字符", 400);
TokenResult token = _tokenService.CreateToken(claims, HttpContext.Connection.RemoteIpAddress?.ToString(), request.DeviceId, request.DeviceName);
return ApiResult.Ok(token);
}
/// <summary>
/// 退出登录:撤销当前客户端的服务端登录会话,令牌立即失效
/// </summary>
[HttpPost]
[EndpointSummary("退出登录")]
[Authorize]
public ApiResult<object?> Logout()
{
if (_currentUser.UserName is string username && _currentUser.GetClaimValue(JwtClaimTypes.Jti) is string jti)
{
_onlineUserStore.SignOutSession(username, jti);
}
return ApiResult<object?>.Ok(null);
}
/// <summary>
/// 获取当前登录用户信息(需携带 Bearer Token)
/// </summary>
[HttpGet]
[EndpointSummary("获取当前登录用户信息")]
[Authorize]
public ApiResult<object?> Me()
{
return ApiResult<object?>.Ok(new
{
UserName = _currentUser.UserName,
NickName = _currentUser.NickName,
});
}
/// <summary>
/// 在线人员列表(需携带 Bearer Token)
/// </summary>
[HttpGet]
[EndpointSummary("获取在线人员列表")]
[Authorize]
public ApiResult<object?> OnlineUsers()
{
IReadOnlyList<OnlineUserInfo> users = _onlineUserStore.GetOnlineUsers();
return ApiResult<object?>.Ok(new
{
Count = users.Count,
Users = users,
});
}
}
public class LoginRequest
{
public string UserName { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string? DeviceId { get; set; }
public string? DeviceName { get; set; }
}
}