116 lines
3.5 KiB
C#
116 lines
3.5 KiB
C#
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; }
|
||
}
|
||
}
|