using Asp.Versioning; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using StoreHub.Framework.Commons; using StoreHub.Framework.Security; using StoreHub.Services; using StoreHub.Services.Dtos; using System.Security.Claims; namespace StoreHub.Controllers { [ApiController] [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]/[action]")] public class AuthController : ControllerBase { private readonly IUserService _userService; private readonly ITokenService _tokenService; private readonly ICurrentUser _currentUser; private readonly IOnlineUserStore _onlineUserStore; public AuthController(IUserService userService, ITokenService tokenService, ICurrentUser currentUser, IOnlineUserStore onlineUserStore) { _userService = userService; _tokenService = tokenService; _currentUser = currentUser; _onlineUserStore = onlineUserStore; } /// /// 登录:校验用户名/密码,签发 JWT(单点登录:同用户的新登录会使旧令牌失效) /// [HttpPost] [AllowAnonymous] public async Task> Login([FromBody] LoginRequest request) { if (request is null || string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Password)) { return ApiResult.Error("用户名或密码不能为空", 400); } UserDto? user = await _userService.LoginAsync(request.UserName, request.Password); if (user is null) { return ApiResult.Error("用户名或密码错误", 401); } var claims = new List { new(JwtClaimTypes.UserId, user.Id.ToString()), new(JwtClaimTypes.UserName, user.UserName), new(JwtClaimTypes.NickName, user.NickName), }; TokenResult token = _tokenService.CreateToken(claims); return ApiResult.Success(token); } /// /// 退出登录:销毁当前用户的服务端在线会话,令牌立即失效 /// [HttpPost] [Authorize] public ApiResult Logout() { if (_currentUser.Id is int userId) { _onlineUserStore.SignOut(userId); } return ApiResult.Success(null); } /// /// 获取当前登录用户信息(需携带 Bearer Token) /// [HttpGet] [Authorize] public ApiResult Me() { return ApiResult.Success(new { UserId = _currentUser.Id, UserName = _currentUser.UserName, NickName = _currentUser.NickName, }); } /// /// 在线人员列表(需携带 Bearer Token) /// [HttpGet] [Authorize] public ApiResult OnlineUsers() { IReadOnlyList users = _onlineUserStore.GetOnlineUsers(); return ApiResult.Success(new { Count = users.Count, Users = users, }); } } public class LoginRequest { public string UserName { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; } }