using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Mapster; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using NPin.Framework.Upms.Domain.Entities; using NPin.Framework.Upms.Domain.Repositories; using NPin.Framework.Upms.Domain.Shared.Consts; using NPin.Framework.Upms.Domain.Shared.Dtos; using NPin.Framework.Upms.Domain.Shared.Etos; using NPin.Framework.Upms.Domain.Shared.Options; using Volo.Abp.Domain.Services; using Volo.Abp.EventBus.Local; using Volo.Abp.Security.Claims; namespace NPin.Framework.Upms.Domain.Managers; public interface IAccountManager { /// /// 创建 RefreshToken /// /// /// string CreateRefreshToken(Guid userId); /// /// 获取 AccessToken /// /// /// Task CreateAccessTokenAsync(Guid userId); /// /// 重置密码 /// /// /// /// Task RestPasswordAsync(Guid userId, string password); /// /// 修改密码 /// /// /// /// /// Task UpdatePasswordAsync(Guid userId, string newPassword, string oldPassword); } public class AccountManager : DomainService, IAccountManager { private readonly IUserRepository _repository; private readonly ILocalEventBus _localEventBus; private readonly JwtOptions _jwtOptions; private readonly RefreshJwtOptions _refreshJwtOptions; private readonly UserManager _userManager; private IHttpContextAccessor _httpContextAccessor; public AccountManager( IUserRepository repository, ILocalEventBus localEventBus, IOptions jwtOptions, IOptions refreshJwtOptions, UserManager userManager, IHttpContextAccessor httpContextAccessor) { _repository = repository; _localEventBus = localEventBus; _jwtOptions = jwtOptions.Value; _refreshJwtOptions = refreshJwtOptions.Value; _userManager = userManager; _httpContextAccessor = httpContextAccessor; } /// /// 根据用户Id获取AccessToken /// /// /// public async Task CreateAccessTokenAsync(Guid userId) { var userInfo = await _userManager.GetInfoByCacheAsync(userId); if (!userInfo.User.IsEnabled) { throw new UserFriendlyException("该用户已被禁用,请联系管理员进行恢复"); } // http请求 if (_httpContextAccessor.HttpContext is not null) { // TODO eto 与 entity 保证 var loginLogEntity = LoginLogEntity.GetInfoByHttpContext(_httpContextAccessor.HttpContext); var loginEto = loginLogEntity.Adapt(); loginEto.Username = userInfo.User.Username; loginEto.UserId = userInfo.User.Id; // 异步 _ = _localEventBus.PublishAsync(loginEto); } return CreateAccessToken(UserInfoToClaims(userInfo)); } private string CreateAccessToken(List> kvs) { var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtOptions.SecurityKey)); // RSA2 var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var claims = kvs.Select(x => new Claim(x.Key, x.Value)).ToList(); var token = new JwtSecurityToken( issuer: _jwtOptions.Issuer, audience: _jwtOptions.Audience, claims: claims, expires: DateTime.Now.AddMinutes(_jwtOptions.ExpiresMinuteTime), notBefore: DateTime.Now, signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); } public string CreateRefreshToken(Guid userId) { throw new NotImplementedException(); } private List> UserInfoToClaims(UserFullDto dto) { var claims = new List>(); AddToClaim(claims, AbpClaimTypes.UserId, dto.User.Id.ToString()); AddToClaim(claims, AbpClaimTypes.UserName, dto.User.Username); // TODO 各种 Claim // 超级管理员 if (UserConst.Admin.Equals(dto.User.Username)) { AddToClaim(claims, TokenTypeConst.Permission, UserConst.AdminPermissionCode); AddToClaim(claims, TokenTypeConst.Roles, UserConst.AdminRoleCode); } else { } return claims; } private void AddToClaim(List> claims, string key, string value) { claims.Add(new KeyValuePair(key, value)); } /// /// 重置密码(仅执行最终重置,无前序判断) /// /// /// /// public async Task RestPasswordAsync(Guid userId, string password) { var user = await _repository.GetByIdAsync(userId); user.EncryptPassword.Password = password; user.BuildPassword(); return await _repository.UpdateAsync(user); } public Task UpdatePasswordAsync(Guid userId, string newPassword, string oldPassword) { throw new NotImplementedException(); } }