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] [ApiVersion("1.0")] [Route("/v{version:apiVersion}/[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 _logger; public AuthController(ITokenService tokenService, ICurrentUser currentUser, IOnlineUserStore onlineUserStore, ILogger logger, IUserAuthenticationService users) { _users = users; _tokenService = tokenService; _currentUser = currentUser; _onlineUserStore = onlineUserStore; _logger = logger; } /// /// 登录:校验用户名/密码,签发 JWT(单点登录:同用户的新登录会使旧令牌失效) /// [HttpPost] [AllowAnonymous] public async Task 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 { new(JwtClaimTypes.UserName, user.UserName), }; TokenResult token = _tokenService.CreateToken(claims); return ApiResult.Ok(token); } /// /// 退出登录:销毁当前用户的服务端在线会话,令牌立即失效 /// [HttpPost] [Authorize] public ApiResult Logout() { if (_currentUser.UserName is string username) { _onlineUserStore.SignOut(username); } return ApiResult.Ok(null); } /// /// 获取当前登录用户信息(需携带 Bearer Token) /// [HttpGet] [Authorize] public ApiResult Me() { return ApiResult.Ok(new { UserName = _currentUser.UserName, NickName = _currentUser.NickName, }); } /// /// 在线人员列表(需携带 Bearer Token) /// [HttpGet] [Authorize] public ApiResult OnlineUsers() { IReadOnlyList users = _onlineUserStore.GetOnlineUsers(); return ApiResult.Ok(new { Count = users.Count, Users = users, }); } } public class LoginRequest { public string UserName { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; } }