🍈 feat(UserManner): 使用缓存管理用户session信息
This commit is contained in:
parent
e6be8a200e
commit
086b6715cd
@ -24,6 +24,7 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
private readonly SysRoleService _sysRoleService;
|
private readonly SysRoleService _sysRoleService;
|
||||||
private readonly SysOnlineUserService _sysOnlineUserService;
|
private readonly SysOnlineUserService _sysOnlineUserService;
|
||||||
private readonly SysConfigService _sysConfigService;
|
private readonly SysConfigService _sysConfigService;
|
||||||
|
private readonly SysAuthService _sysAuthService;
|
||||||
private readonly ICaptcha _captcha;
|
private readonly ICaptcha _captcha;
|
||||||
private readonly SysCacheService _sysCacheService;
|
private readonly SysCacheService _sysCacheService;
|
||||||
|
|
||||||
@ -33,9 +34,11 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
SysRoleService sysRoleService,
|
SysRoleService sysRoleService,
|
||||||
SysOnlineUserService sysOnlineUserService,
|
SysOnlineUserService sysOnlineUserService,
|
||||||
SysConfigService sysConfigService,
|
SysConfigService sysConfigService,
|
||||||
|
SysAuthService sysAuthService,
|
||||||
ICaptcha captcha,
|
ICaptcha captcha,
|
||||||
SysCacheService sysCacheService)
|
SysCacheService sysCacheService)
|
||||||
{
|
{
|
||||||
|
_sysAuthService = sysAuthService;
|
||||||
_appUserManager = appUserManager;
|
_appUserManager = appUserManager;
|
||||||
_sysUserRep = sysUserRep;
|
_sysUserRep = sysUserRep;
|
||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
@ -100,8 +103,7 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
|
|
||||||
// 登录成功则清空密码错误次数
|
// 登录成功则清空密码错误次数
|
||||||
_sysCacheService.Remove(keyPasswordErrorTimes);
|
_sysCacheService.Remove(keyPasswordErrorTimes);
|
||||||
|
return await _sysAuthService.CreateToken(user, LoginModeEnum.APP);
|
||||||
return await CreateToken(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -149,54 +151,7 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
// 账号是否存在
|
// 账号是否存在
|
||||||
var user = await _sysUserRep.AsQueryable().Includes(u => u.SysOrg).IgnoreTenant().FirstAsync(u => u.Phone.Equals(input.Phone));
|
var user = await _sysUserRep.AsQueryable().Includes(u => u.SysOrg).IgnoreTenant().FirstAsync(u => u.Phone.Equals(input.Phone));
|
||||||
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
||||||
|
return await _sysAuthService.CreateToken(user, LoginModeEnum.APP);
|
||||||
return await CreateToken(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 生成Token令牌 🔖
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user"></param>
|
|
||||||
/// <param name="loginMode"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[NonAction]
|
|
||||||
public virtual async Task<LoginOutput> CreateToken(SysUser user, LoginModeEnum loginMode = LoginModeEnum.APP)
|
|
||||||
{
|
|
||||||
// 单用户登录
|
|
||||||
await _sysOnlineUserService.SingleLogin(user.Id, loginMode);
|
|
||||||
|
|
||||||
// 生成Token令牌
|
|
||||||
var tokenExpire = await _sysConfigService.GetTokenExpire();
|
|
||||||
var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ AppClaimConst.UserId, user.Id },
|
|
||||||
{ AppClaimConst.TenantId, user.TenantId },
|
|
||||||
{ AppClaimConst.Account, user.Account },
|
|
||||||
{ AppClaimConst.RealName, user.RealName },
|
|
||||||
{ AppClaimConst.AccountType, user.AccountType },
|
|
||||||
{ AppClaimConst.OrgId, user.OrgId },
|
|
||||||
{ AppClaimConst.OrgName, user.SysOrg?.Name },
|
|
||||||
{ AppClaimConst.OrgType, user.SysOrg?.Type },
|
|
||||||
{ AppClaimConst.OrgLevel, user.SysOrg?.Level },
|
|
||||||
{ ClaimConst.LoginMode, loginMode },
|
|
||||||
{ ClaimConst.TokenVersion, user.TokenVersion },
|
|
||||||
}, tokenExpire);
|
|
||||||
|
|
||||||
// 生成刷新Token令牌
|
|
||||||
var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire();
|
|
||||||
var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
|
|
||||||
|
|
||||||
// 设置响应报文头
|
|
||||||
_httpContextAccessor.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken);
|
|
||||||
|
|
||||||
// 缓存用户Token版本
|
|
||||||
_sysCacheService.Set($"{CacheConst.KeyUserToken}{user.Id}", $"{user.TokenVersion}");
|
|
||||||
|
|
||||||
return new LoginOutput
|
|
||||||
{
|
|
||||||
AccessToken = accessToken,
|
|
||||||
RefreshToken = refreshToken
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -261,6 +216,7 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
if (string.IsNullOrWhiteSpace(_appUserManager.Account))
|
if (string.IsNullOrWhiteSpace(_appUserManager.Account))
|
||||||
throw Oops.Oh(ErrorCodeEnum.D1011);
|
throw Oops.Oh(ErrorCodeEnum.D1011);
|
||||||
|
|
||||||
|
_appUserManager.RemoveSession(_appUserManager.UserId);
|
||||||
_httpContextAccessor.HttpContext.SignoutToSwagger();
|
_httpContextAccessor.HttpContext.SignoutToSwagger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,16 +6,25 @@
|
|||||||
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Admin.NET.Application.Service.App;
|
namespace Admin.NET.Application;
|
||||||
|
|
||||||
public class AppUserManager : UserManager
|
/// <summary>
|
||||||
|
/// 业务层用户Session管理
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sysCacheService"></param>
|
||||||
|
/// <param name="httpContextAccessor"></param>
|
||||||
|
public class AppUserManager(
|
||||||
|
SysCacheService sysCacheService,
|
||||||
|
IHttpContextAccessor httpContextAccessor)
|
||||||
|
: UserManager(sysCacheService, httpContextAccessor)
|
||||||
|
{
|
||||||
|
// 扩展属性
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户会话信息
|
||||||
|
/// </summary>
|
||||||
|
public partial class UserSessionDao
|
||||||
{
|
{
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
||||||
|
|
||||||
public AppUserManager(IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
|
|
||||||
{
|
|
||||||
_httpContextAccessor = httpContextAccessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 扩展属性
|
// 扩展属性
|
||||||
}
|
}
|
||||||
@ -16,12 +16,18 @@ namespace Admin.NET.Core.ApiKeyAuth;
|
|||||||
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
|
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
|
||||||
{
|
{
|
||||||
public const string AuthenticationScheme = "ApiKey";
|
public const string AuthenticationScheme = "ApiKey";
|
||||||
|
private readonly SysAuthService _sysAuthService;
|
||||||
|
private readonly UserManager _userManager;
|
||||||
|
|
||||||
public ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions> options,
|
public ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions> options,
|
||||||
ILoggerFactory logger,
|
ILoggerFactory logger,
|
||||||
UrlEncoder encoder)
|
UrlEncoder encoder,
|
||||||
|
UserManager userManager,
|
||||||
|
SysAuthService sysAuthService)
|
||||||
: base(options, logger, encoder)
|
: base(options, logger, encoder)
|
||||||
{
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_sysAuthService = sysAuthService;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||||
@ -39,15 +45,12 @@ public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthentic
|
|||||||
identity.AddClaims(
|
identity.AddClaims(
|
||||||
[
|
[
|
||||||
new Claim(ClaimConst.UserId, acsInfo.BindUserId + ""),
|
new Claim(ClaimConst.UserId, acsInfo.BindUserId + ""),
|
||||||
new Claim(ClaimConst.TenantId, acsInfo.BindTenantId + ""),
|
|
||||||
new Claim(ClaimConst.Account, acsInfo.BindUser.Account + ""),
|
|
||||||
new Claim(ClaimConst.RealName, acsInfo.BindUser.RealName),
|
|
||||||
new Claim(ClaimConst.AccountType, ((int)acsInfo.BindUser.AccountType).ToString()),
|
|
||||||
new Claim(ClaimConst.OrgId, acsInfo.BindUser.OrgId + ""),
|
|
||||||
new Claim(ClaimConst.OrgName, acsInfo.BindUser.SysOrg?.Name + ""),
|
|
||||||
new Claim(ClaimConst.OrgType, acsInfo.BindUser.SysOrg?.Type + ""),
|
|
||||||
new Claim(ClaimConst.TokenVersion, "1")
|
new Claim(ClaimConst.TokenVersion, "1")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 设置用户Session缓存
|
||||||
|
if (!_userManager.ExistSession(acsInfo.Id)) await _sysAuthService.CreateToken(acsInfo.BindUser);
|
||||||
|
|
||||||
var user = new ClaimsPrincipal(identity);
|
var user = new ClaimsPrincipal(identity);
|
||||||
return AuthenticateResult.Success(new AuthenticationTicket(user, AuthenticationScheme));
|
return AuthenticateResult.Success(new AuthenticationTicket(user, AuthenticationScheme));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,11 @@ namespace Admin.NET.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CacheConst
|
public class CacheConst
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用户会话缓存
|
||||||
|
/// </summary>
|
||||||
|
public const string KeyUserSession = "sys_user_session:";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户Token版本缓存
|
/// 用户Token版本缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -11,73 +11,85 @@ namespace Admin.NET.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ClaimConst
|
public class ClaimConst
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 应用Id
|
|
||||||
/// </summary>
|
|
||||||
public const string AppId = "AppId";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 租户Id
|
|
||||||
/// </summary>
|
|
||||||
public const string TenantId = "TenantId";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户Id
|
/// 用户Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string UserId = "UserId";
|
public const string UserId = "UserId";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 账号
|
|
||||||
/// </summary>
|
|
||||||
public const string Account = "Account";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 真实姓名
|
|
||||||
/// </summary>
|
|
||||||
public const string RealName = "RealName";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 昵称
|
|
||||||
/// </summary>
|
|
||||||
public const string NickName = "NickName";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 账号类型
|
|
||||||
/// </summary>
|
|
||||||
public const string AccountType = "AccountType";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 组织机构Id
|
|
||||||
/// </summary>
|
|
||||||
public const string OrgId = "OrgId";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 组织机构名称
|
|
||||||
/// </summary>
|
|
||||||
public const string OrgName = "OrgName";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 组织机构类型
|
|
||||||
/// </summary>
|
|
||||||
public const string OrgType = "OrgType";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 组织机构级别
|
|
||||||
/// </summary>
|
|
||||||
public const string OrgLevel = "OrgLevel";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 登录模式PC、APP
|
|
||||||
/// </summary>
|
|
||||||
public const string LoginMode = "LoginMode";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Token版本号
|
/// Token版本号
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string TokenVersion = "TokenVersion";
|
public const string TokenVersion = "TokenVersion";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用Id
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string AppId = "AppId";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 租户Id
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string TenantId = "TenantId";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账号
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string Account = "Account";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 真实姓名
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string RealName = "RealName";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 昵称
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string NickName = "NickName";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账号类型
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string AccountType = "AccountType";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构Id
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string OrgId = "OrgId";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构名称
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string OrgName = "OrgName";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构类型
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string OrgType = "OrgType";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构级别
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string OrgLevel = "OrgLevel";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登录模式PC、APP
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
|
public const string LoginMode = "LoginMode";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 微信OpenId
|
/// 微信OpenId
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("参数已从请求上下文中移除,请通过UserManger获取")]
|
||||||
public const string OpenId = "OpenId";
|
public const string OpenId = "OpenId";
|
||||||
}
|
}
|
||||||
@ -15,6 +15,7 @@ public class CommonConst
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 系统管理员角色编码
|
/// 系统管理员角色编码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Description("系统管理员角色编码")]
|
||||||
public const string SysAdminRole = "sys_admin";
|
public const string SysAdminRole = "sys_admin";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -19,10 +19,14 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
|||||||
|
|
||||||
private readonly SysMessageService _sysMessageService;
|
private readonly SysMessageService _sysMessageService;
|
||||||
private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _onlineUserHubContext;
|
private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _onlineUserHubContext;
|
||||||
|
private readonly UserManager _userManager;
|
||||||
|
|
||||||
public OnlineUserHub(SysMessageService sysMessageService,
|
public OnlineUserHub(
|
||||||
|
UserManager userManager,
|
||||||
|
SysMessageService sysMessageService,
|
||||||
IHubContext<OnlineUserHub, IOnlineUserHub> onlineUserHubContext)
|
IHubContext<OnlineUserHub, IOnlineUserHub> onlineUserHubContext)
|
||||||
{
|
{
|
||||||
|
_userManager = userManager;
|
||||||
_sysMessageService = sysMessageService;
|
_sysMessageService = sysMessageService;
|
||||||
_onlineUserHubContext = onlineUserHubContext;
|
_onlineUserHubContext = onlineUserHubContext;
|
||||||
}
|
}
|
||||||
@ -34,28 +38,22 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
|||||||
public override async Task OnConnectedAsync()
|
public override async Task OnConnectedAsync()
|
||||||
{
|
{
|
||||||
var httpContext = Context.GetHttpContext();
|
var httpContext = Context.GetHttpContext();
|
||||||
var userId = (httpContext.User.FindFirst(ClaimConst.UserId)?.Value).ToLong();
|
if (_userManager.UserId < 0 || string.IsNullOrWhiteSpace(_userManager.Account)) return;
|
||||||
var account = httpContext.User.FindFirst(ClaimConst.Account)?.Value;
|
var loginMode = _userManager.LoginMode == 0 ? LoginModeEnum.PC : LoginModeEnum.APP; // 默认PC登录模式
|
||||||
if (userId < 0 || string.IsNullOrWhiteSpace(account)) return;
|
|
||||||
|
|
||||||
var realName = httpContext.User.FindFirst(ClaimConst.RealName)?.Value;
|
|
||||||
var tenantId = (httpContext.User.FindFirst(ClaimConst.TenantId)?.Value).ToLong();
|
|
||||||
var loginMode = (LoginModeEnum)(httpContext.User.FindFirst(ClaimConst.LoginMode)?.Value).ToInt();
|
|
||||||
loginMode = loginMode == 0 ? LoginModeEnum.PC : loginMode; // 默认PC登录模式
|
|
||||||
var device = httpContext.GetClientDeviceInfo().Trim();
|
var device = httpContext.GetClientDeviceInfo().Trim();
|
||||||
var ipAddress = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
|
var ipAddress = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
|
||||||
|
|
||||||
var user = new OnlineUser
|
var user = new OnlineUser
|
||||||
{
|
{
|
||||||
ConnectionId = Context.ConnectionId,
|
ConnectionId = Context.ConnectionId,
|
||||||
UserId = userId,
|
UserId = _userManager.UserId,
|
||||||
UserName = account,
|
UserName = _userManager.Account,
|
||||||
RealName = realName,
|
RealName = _userManager.RealName,
|
||||||
Time = DateTime.Now,
|
Time = DateTime.Now,
|
||||||
Ip = string.IsNullOrWhiteSpace(ipAddress) ? httpContext.GetRemoteIpAddressToIPv4(true) : ipAddress,
|
Ip = string.IsNullOrWhiteSpace(ipAddress) ? httpContext.GetRemoteIpAddressToIPv4(true) : ipAddress,
|
||||||
Browser = httpContext.GetClientBrowser(),
|
Browser = httpContext.GetClientBrowser(),
|
||||||
Os = httpContext.GetClientOs(),
|
Os = httpContext.GetClientOs(),
|
||||||
TenantId = tenantId,
|
TenantId = _userManager.TenantId ?? 0,
|
||||||
LoginMode = loginMode,
|
LoginMode = loginMode,
|
||||||
Device = device
|
Device = device
|
||||||
};
|
};
|
||||||
@ -66,7 +64,7 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
|||||||
await _onlineUserHubContext.Groups.AddToGroupAsync(Context.ConnectionId, groupName);
|
await _onlineUserHubContext.Groups.AddToGroupAsync(Context.ConnectionId, groupName);
|
||||||
|
|
||||||
// 更新在线用户列表
|
// 更新在线用户列表
|
||||||
var userList = SysCacheService.HashGetAll<OnlineUser>(CacheConst.KeyUserOnline).Values.Where(u => u.TenantId == tenantId).ToList();
|
var userList = SysCacheService.HashGetAll<OnlineUser>(CacheConst.KeyUserOnline).Values.Where(u => u.TenantId == _userManager.TenantId).ToList();
|
||||||
await _onlineUserHubContext.Clients.Groups(groupName).OnlineUserList(new OnlineUserList
|
await _onlineUserHubContext.Clients.Groups(groupName).OnlineUserList(new OnlineUserList
|
||||||
{
|
{
|
||||||
RealName = user.RealName,
|
RealName = user.RealName,
|
||||||
|
|||||||
@ -13,6 +13,7 @@ namespace Admin.NET.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
||||||
{
|
{
|
||||||
|
private static readonly Lazy<UserManager> _userManager = new(() => App.GetService<UserManager>());
|
||||||
private readonly IServiceScope _serviceScope;
|
private readonly IServiceScope _serviceScope;
|
||||||
private readonly IEventPublisher _eventPublisher;
|
private readonly IEventPublisher _eventPublisher;
|
||||||
private readonly ILogger<DatabaseLoggingWriter> _logger;
|
private readonly ILogger<DatabaseLoggingWriter> _logger;
|
||||||
@ -100,10 +101,11 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
|||||||
if (loggingMonitor.authorizationClaims != null)
|
if (loggingMonitor.authorizationClaims != null)
|
||||||
{
|
{
|
||||||
var authDict = (loggingMonitor.authorizationClaims as IEnumerable<dynamic>)!.ToDictionary(u => u.type.ToString(), u => u.value.ToString());
|
var authDict = (loggingMonitor.authorizationClaims as IEnumerable<dynamic>)!.ToDictionary(u => u.type.ToString(), u => u.value.ToString());
|
||||||
account = authDict?.GetValueOrDefault(ClaimConst.Account);
|
userId = authDict.GetValueOrDefault(ClaimConst.UserId);
|
||||||
realName = authDict?.GetValueOrDefault(ClaimConst.RealName);
|
var userSession = _userManager.Value.GetSession(userId);
|
||||||
tenantId = authDict?.GetValueOrDefault(ClaimConst.TenantId);
|
account = userSession?.Account;
|
||||||
userId = authDict?.GetValueOrDefault(ClaimConst.UserId);
|
realName = userSession?.RealName;
|
||||||
|
tenantId = userSession?.TenantId?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 优先获取 X-Forwarded-For 头部信息携带的IP地址(如nginx代理配置转发)
|
// 优先获取 X-Forwarded-For 头部信息携带的IP地址(如nginx代理配置转发)
|
||||||
|
|||||||
@ -15,12 +15,15 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
|||||||
{
|
{
|
||||||
private readonly IServiceScope _serviceScope;
|
private readonly IServiceScope _serviceScope;
|
||||||
private readonly ElasticsearchClient _esClient;
|
private readonly ElasticsearchClient _esClient;
|
||||||
|
private readonly SysCacheService _sysCacheService;
|
||||||
private readonly SysConfigService _sysConfigService;
|
private readonly SysConfigService _sysConfigService;
|
||||||
|
private static readonly Lazy<UserManager> _userManager = new(() => App.GetService<UserManager>());
|
||||||
|
|
||||||
public ElasticSearchLoggingWriter(IServiceScopeFactory scopeFactory)
|
public ElasticSearchLoggingWriter(IServiceScopeFactory scopeFactory)
|
||||||
{
|
{
|
||||||
_serviceScope = scopeFactory.CreateScope();
|
_serviceScope = scopeFactory.CreateScope();
|
||||||
_esClient = _serviceScope.ServiceProvider.GetRequiredService<ElasticsearchClient>();
|
_esClient = _serviceScope.ServiceProvider.GetRequiredService<ElasticsearchClient>();
|
||||||
|
_sysCacheService = _serviceScope.ServiceProvider.GetRequiredService<SysCacheService>();
|
||||||
_sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
|
_sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,17 +46,17 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
|||||||
string account = "", realName = "", userId = "", tenantId = "";
|
string account = "", realName = "", userId = "", tenantId = "";
|
||||||
if (loggingMonitor.authorizationClaims != null)
|
if (loggingMonitor.authorizationClaims != null)
|
||||||
{
|
{
|
||||||
|
UserSessionDao userSession = null;
|
||||||
foreach (var item in loggingMonitor.authorizationClaims)
|
foreach (var item in loggingMonitor.authorizationClaims)
|
||||||
{
|
{
|
||||||
if (item.type == ClaimConst.Account)
|
if (item.type != ClaimConst.UserId) continue;
|
||||||
account = item.value;
|
|
||||||
if (item.type == ClaimConst.RealName)
|
|
||||||
realName = item.value;
|
|
||||||
if (item.type == ClaimConst.TenantId)
|
|
||||||
tenantId = item.value;
|
|
||||||
if (item.type == ClaimConst.UserId)
|
|
||||||
userId = item.value;
|
userId = item.value;
|
||||||
|
userSession = _userManager.Value?.GetSession(userId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
tenantId = userSession?.TenantId.ToString();
|
||||||
|
realName = userSession?.RealName;
|
||||||
|
account = userSession?.Account;
|
||||||
}
|
}
|
||||||
|
|
||||||
string remoteIPv4 = loggingMonitor.remoteIPv4;
|
string remoteIPv4 = loggingMonitor.remoteIPv4;
|
||||||
|
|||||||
@ -233,17 +233,24 @@ public class SysAuthService : IDynamicApiController, ITransient
|
|||||||
var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
|
var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ ClaimConst.UserId, user.Id },
|
{ ClaimConst.UserId, user.Id },
|
||||||
{ ClaimConst.TenantId, user.TenantId },
|
|
||||||
{ ClaimConst.Account, user.Account },
|
|
||||||
{ ClaimConst.RealName, user.RealName },
|
|
||||||
{ ClaimConst.AccountType, user.AccountType },
|
|
||||||
{ ClaimConst.OrgId, user.OrgId },
|
|
||||||
{ ClaimConst.OrgName, user.SysOrg?.Name },
|
|
||||||
{ ClaimConst.OrgType, user.SysOrg?.Type },
|
|
||||||
{ ClaimConst.OrgLevel, user.SysOrg?.Level },
|
|
||||||
{ ClaimConst.TokenVersion, user.TokenVersion },
|
{ ClaimConst.TokenVersion, user.TokenVersion },
|
||||||
}, tokenExpire);
|
}, tokenExpire);
|
||||||
|
|
||||||
|
// 缓存用户Session
|
||||||
|
_userManager.SetSession(new()
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
TenantId = user.TenantId,
|
||||||
|
Account = user.Account,
|
||||||
|
RealName = user.RealName,
|
||||||
|
AccountType = user.AccountType,
|
||||||
|
OrgId = user.OrgId,
|
||||||
|
OrgName = user.SysOrg?.Name,
|
||||||
|
OrgType = user.SysOrg?.Type,
|
||||||
|
OrgLevel = user.SysOrg?.Level,
|
||||||
|
TokenVersion = user.TokenVersion,
|
||||||
|
}, TimeSpan.FromMinutes(tokenExpire));
|
||||||
|
|
||||||
// 生成刷新Token令牌
|
// 生成刷新Token令牌
|
||||||
var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire();
|
var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire();
|
||||||
var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
|
var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
|
||||||
@ -358,6 +365,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
|||||||
|
|
||||||
// 发布系统退出事件
|
// 发布系统退出事件
|
||||||
await _eventPublisher.PublishAsync(UserEventTypeEnum.Logout, _userManager);
|
await _eventPublisher.PublishAsync(UserEventTypeEnum.Logout, _userManager);
|
||||||
|
_userManager.RemoveSession(_userManager.UserId);
|
||||||
|
|
||||||
// 退出Swagger/设置无效Token响应头
|
// 退出Swagger/设置无效Token响应头
|
||||||
_httpContextAccessor.HttpContext.SignoutToSwagger();
|
_httpContextAccessor.HttpContext.SignoutToSwagger();
|
||||||
|
|||||||
@ -17,15 +17,22 @@ public class SysOpenAccessService : IDynamicApiController, ITransient
|
|||||||
{
|
{
|
||||||
private readonly SqlSugarRepository<SysOpenAccess> _sysOpenAccessRep;
|
private readonly SqlSugarRepository<SysOpenAccess> _sysOpenAccessRep;
|
||||||
private readonly SysCacheService _sysCacheService;
|
private readonly SysCacheService _sysCacheService;
|
||||||
|
private readonly SysAuthService _sysAuthService;
|
||||||
|
private readonly UserManager _userManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开放接口身份服务构造函数
|
/// 开放接口身份服务构造函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SysOpenAccessService(SqlSugarRepository<SysOpenAccess> sysOpenAccessRep,
|
public SysOpenAccessService(
|
||||||
SysCacheService sysCacheService)
|
SqlSugarRepository<SysOpenAccess> sysOpenAccessRep,
|
||||||
|
SysCacheService sysCacheService,
|
||||||
|
SysAuthService sysAuthService,
|
||||||
|
UserManager userManager)
|
||||||
{
|
{
|
||||||
_sysOpenAccessRep = sysOpenAccessRep;
|
_sysOpenAccessRep = sysOpenAccessRep;
|
||||||
_sysCacheService = sysCacheService;
|
_sysCacheService = sysCacheService;
|
||||||
|
_sysAuthService = sysAuthService;
|
||||||
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -156,6 +163,17 @@ public class SysOpenAccessService : IDynamicApiController, ITransient
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据 Key 获取对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="openAccess"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[NonAction]
|
||||||
|
private async Task TryCreateSession(SysOpenAccess openAccess)
|
||||||
|
{
|
||||||
|
if (!_userManager.ExistSession(openAccess.Id)) await _sysAuthService.CreateToken(openAccess.BindUser);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signature 身份验证事件默认实现
|
/// Signature 身份验证事件默认实现
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -188,15 +206,9 @@ public class SysOpenAccessService : IDynamicApiController, ITransient
|
|||||||
identity.AddClaims(
|
identity.AddClaims(
|
||||||
[
|
[
|
||||||
new Claim(ClaimConst.UserId, openAccess.BindUserId + ""),
|
new Claim(ClaimConst.UserId, openAccess.BindUserId + ""),
|
||||||
new Claim(ClaimConst.TenantId, openAccess.BindTenantId + ""),
|
|
||||||
new Claim(ClaimConst.Account, openAccess.BindUser.Account + ""),
|
|
||||||
new Claim(ClaimConst.RealName, openAccess.BindUser.RealName),
|
|
||||||
new Claim(ClaimConst.AccountType, ((int)openAccess.BindUser.AccountType).ToString()),
|
|
||||||
new Claim(ClaimConst.OrgId, openAccess.BindUser.OrgId + ""),
|
|
||||||
new Claim(ClaimConst.OrgName, openAccess.BindUser.SysOrg?.Name + ""),
|
|
||||||
new Claim(ClaimConst.OrgType, openAccess.BindUser.SysOrg?.Type + ""),
|
|
||||||
new Claim(ClaimConst.TokenVersion, openAccess.BindUser.TokenVersion + ""),
|
new Claim(ClaimConst.TokenVersion, openAccess.BindUser.TokenVersion + ""),
|
||||||
]);
|
]);
|
||||||
|
openAccessService.TryCreateSession(openAccess).GetAwaiter().GetResult();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -172,7 +172,7 @@ public class SysSerialService : IDynamicApiController, ITransient
|
|||||||
public async Task<string> NextSeqNo(SerialTypeEnum? type, bool isGlobal = false, bool isTran = true)
|
public async Task<string> NextSeqNo(SerialTypeEnum? type, bool isGlobal = false, bool isTran = true)
|
||||||
{
|
{
|
||||||
// 获取租户Id, 以及分布式锁缓存键名
|
// 获取租户Id, 以及分布式锁缓存键名
|
||||||
long tenantId = isGlobal ? SqlSugarConst.DefaultTenantId : _userManager.TenantId;
|
long? tenantId = isGlobal ? SqlSugarConst.DefaultTenantId : _userManager.TenantId;
|
||||||
string cacheKey = $"{CacheConst.KeySerialLock}:{tenantId}:{type}";
|
string cacheKey = $"{CacheConst.KeySerialLock}:{tenantId}:{type}";
|
||||||
|
|
||||||
// 获取分布式锁
|
// 获取分布式锁
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class SysTenantService : IDynamicApiController, ITransient
|
|||||||
private readonly SysConfigService _sysConfigService;
|
private readonly SysConfigService _sysConfigService;
|
||||||
private readonly SysCacheService _sysCacheService;
|
private readonly SysCacheService _sysCacheService;
|
||||||
private readonly IEventPublisher _eventPublisher;
|
private readonly IEventPublisher _eventPublisher;
|
||||||
|
private readonly UserManager _userManager;
|
||||||
|
|
||||||
public SysTenantService(SqlSugarRepository<SysTenant> sysTenantRep,
|
public SysTenantService(SqlSugarRepository<SysTenant> sysTenantRep,
|
||||||
SqlSugarRepository<SysOrg> sysOrgRep,
|
SqlSugarRepository<SysOrg> sysOrgRep,
|
||||||
@ -560,7 +561,7 @@ public class SysTenantService : IDynamicApiController, ITransient
|
|||||||
//// 还可以根据域名判断租户
|
//// 还可以根据域名判断租户
|
||||||
//var host = App.HttpContext.Request.Host.ToString();
|
//var host = App.HttpContext.Request.Host.ToString();
|
||||||
|
|
||||||
if (tenantId < 1) tenantId = long.Parse(App.User?.FindFirst(ClaimConst.TenantId)?.Value ?? "0");
|
if (tenantId < 1) tenantId = _userManager?.TenantId ?? 0;
|
||||||
if (tenantId < 1) tenantId = SqlSugarConst.DefaultTenantId;
|
if (tenantId < 1) tenantId = SqlSugarConst.DefaultTenantId;
|
||||||
var tenant = await _sysTenantRep.GetFirstAsync(u => u.Id == tenantId) ?? throw Oops.Oh($"租户信息不存在:{tenantId}");
|
var tenant = await _sysTenantRep.GetFirstAsync(u => u.Id == tenantId) ?? throw Oops.Oh($"租户信息不存在:{tenantId}");
|
||||||
|
|
||||||
@ -613,7 +614,7 @@ public class SysTenantService : IDynamicApiController, ITransient
|
|||||||
[DisplayName("保存系统信息")]
|
[DisplayName("保存系统信息")]
|
||||||
public async Task SaveSysInfo(SysInfoInput input)
|
public async Task SaveSysInfo(SysInfoInput input)
|
||||||
{
|
{
|
||||||
input.TenantId = input.TenantId < 1 ? long.Parse(App.User?.FindFirst(ClaimConst.TenantId)?.Value ?? "0") : input.TenantId;
|
input.TenantId = input.TenantId < 1 ? (_userManager.TenantId ?? 0) : input.TenantId;
|
||||||
var tenant = await _sysTenantRep.GetFirstAsync(u => u.Id == input.TenantId) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
|
var tenant = await _sysTenantRep.GetFirstAsync(u => u.Id == input.TenantId) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
|
||||||
tenant = input.Adapt<SysTenant>();
|
tenant = input.Adapt<SysTenant>();
|
||||||
tenant.Id = input.TenantId;
|
tenant.Id = input.TenantId;
|
||||||
|
|||||||
@ -9,92 +9,120 @@ namespace Admin.NET.Core;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前登录用户信息
|
/// 当前登录用户信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UserManager : IScoped
|
public class UserManager (
|
||||||
|
SysCacheService sysCacheService,
|
||||||
|
IHttpContextAccessor httpContextAccessor) : UserSessionDao, IScoped
|
||||||
{
|
{
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
/// <summary>
|
||||||
|
/// 用户Session
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
private UserSessionDao Session { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 应用Id
|
/// 代理对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long AppId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AppId)?.Value).ToLong();
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
/// <summary>
|
protected UserSessionDao session => Session ??= sysCacheService.Get<UserSessionDao>(CacheConst.KeyUserSession + UserId);
|
||||||
/// 租户Id
|
|
||||||
/// </summary>
|
|
||||||
public long TenantId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.TenantId)?.Value).ToLong();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户Id
|
/// 用户Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long UserId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.UserId)?.Value).ToLong();
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public override long UserId => (httpContextAccessor.HttpContext?.User.FindFirst(nameof(UserId))?.Value).ToLong();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用Id
|
||||||
|
/// </summary>
|
||||||
|
public override long? AppId => session?.AppId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 租户Id
|
||||||
|
/// </summary>
|
||||||
|
public override long? TenantId => session?.TenantId;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户账号
|
/// 用户账号
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Account => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.Account)?.Value;
|
public override string Account => session?.Account;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 真实姓名
|
/// 真实姓名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string RealName => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.RealName)?.Value;
|
public override string RealName => session?.RealName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 昵称
|
/// 昵称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string NickName => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.NickName)?.Value;
|
public override string NickName => session?.NickName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 账号类型
|
/// 账号类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AccountTypeEnum? AccountType => int.TryParse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value, out var val) ? (AccountTypeEnum?)val : null;
|
public override AccountTypeEnum? AccountType => session?.AccountType;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否超级管理员
|
|
||||||
/// </summary>
|
|
||||||
public bool SuperAdmin => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否系统管理员
|
|
||||||
/// </summary>
|
|
||||||
public bool SysAdmin => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SysAdmin).ToString();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组织机构Id
|
/// 组织机构Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long OrgId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OrgId)?.Value).ToLong();
|
public override long OrgId => session?.OrgId ?? 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组织机构名称
|
/// 组织机构名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OrgName => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OrgName)?.Value);
|
public override string OrgName => session?.OrgName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组织机构Id
|
/// 组织机构Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OrgType => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OrgType)?.Value);
|
public override string OrgType => session?.OrgType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组织机构级别
|
/// 组织机构级别
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int OrgLevel => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OrgLevel)?.Value).ToInt();
|
public override int? OrgLevel => session?.OrgLevel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 登录模式
|
/// 登录模式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int LoginMode => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.LoginMode)?.Value).ToInt();
|
public override LoginModeEnum? LoginMode => session?.LoginMode;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Token版本号
|
|
||||||
/// </summary>
|
|
||||||
public int TokenVersion => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.TokenVersion)?.Value).ToInt();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 微信OpenId
|
/// 微信OpenId
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OpenId => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OpenId)?.Value;
|
public override string OpenId => session?.OpenId;
|
||||||
|
|
||||||
public UserManager(IHttpContextAccessor httpContextAccessor)
|
/// <summary>
|
||||||
|
/// 用户Session是否存在
|
||||||
|
/// </summary>
|
||||||
|
public bool ExistSession(long userId)
|
||||||
{
|
{
|
||||||
_httpContextAccessor = httpContextAccessor;
|
return sysCacheService.ExistKey(CacheConst.KeyUserSession + userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置用户Session
|
||||||
|
/// </summary>
|
||||||
|
public void SetSession(UserSessionDao userSession, TimeSpan expire)
|
||||||
|
{
|
||||||
|
sysCacheService.Set(CacheConst.KeyUserSession + userSession.UserId, userSession, expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除指定用户Session
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveSession(long userId)
|
||||||
|
{
|
||||||
|
sysCacheService.Remove(CacheConst.KeyUserSession + userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定用户Session
|
||||||
|
/// </summary>
|
||||||
|
public UserSessionDao GetSession(dynamic userId)
|
||||||
|
{
|
||||||
|
return sysCacheService.Get<UserSessionDao>(CacheConst.KeyUserSession + userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
97
Admin.NET/Admin.NET.Core/Service/User/UserSessionDao.cs
Normal file
97
Admin.NET/Admin.NET.Core/Service/User/UserSessionDao.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户会话信息
|
||||||
|
/// </summary>
|
||||||
|
public partial class UserSessionDao
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用户Id
|
||||||
|
/// </summary>
|
||||||
|
public virtual long UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 平台应用Id
|
||||||
|
/// </summary>
|
||||||
|
public virtual long? AppId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 租户Id
|
||||||
|
/// </summary>
|
||||||
|
public virtual long? TenantId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账号
|
||||||
|
/// </summary>
|
||||||
|
public virtual string Account { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 真实姓名
|
||||||
|
/// </summary>
|
||||||
|
public virtual string RealName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 昵称
|
||||||
|
/// </summary>
|
||||||
|
public virtual string NickName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账户类型
|
||||||
|
/// </summary>
|
||||||
|
public virtual AccountTypeEnum? AccountType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否超级管理员
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public bool SuperAdmin => AccountType == AccountTypeEnum.SuperAdmin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否系统管理员
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public bool SysAdmin => AccountType == AccountTypeEnum.SysAdmin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构Id
|
||||||
|
/// </summary>
|
||||||
|
public virtual long OrgId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构名称
|
||||||
|
/// </summary>
|
||||||
|
public virtual string OrgName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构类型
|
||||||
|
/// </summary>
|
||||||
|
public virtual string OrgType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组织机构级别
|
||||||
|
/// </summary>
|
||||||
|
public virtual int? OrgLevel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登录模式
|
||||||
|
/// </summary>
|
||||||
|
public virtual LoginModeEnum? LoginMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 微信OpenId
|
||||||
|
/// </summary>
|
||||||
|
public virtual string OpenId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// token版本
|
||||||
|
/// </summary>
|
||||||
|
public virtual long TokenVersion { get; set; }
|
||||||
|
}
|
||||||
@ -13,16 +13,20 @@ namespace Admin.NET.Core.Service;
|
|||||||
public class SysWechatService : IDynamicApiController, ITransient
|
public class SysWechatService : IDynamicApiController, ITransient
|
||||||
{
|
{
|
||||||
private readonly SqlSugarRepository<SysOAuthUser> _sysOAuthUserRep;
|
private readonly SqlSugarRepository<SysOAuthUser> _sysOAuthUserRep;
|
||||||
private readonly SysConfigService _sysConfigService;
|
|
||||||
private readonly WechatApiClientFactory _wechatApiClientFactory;
|
private readonly WechatApiClientFactory _wechatApiClientFactory;
|
||||||
private readonly WechatApiClient _wechatApiClient;
|
private readonly WechatApiClient _wechatApiClient;
|
||||||
|
private readonly SysAuthService _sysAuthService;
|
||||||
|
|
||||||
public SysWechatService(SqlSugarRepository<SysOAuthUser> sysOAuthUserRep,
|
|
||||||
|
public SysWechatService(
|
||||||
|
UserManager userManager,
|
||||||
|
SysAuthService sysAuthService,
|
||||||
SysConfigService sysConfigService,
|
SysConfigService sysConfigService,
|
||||||
|
SqlSugarRepository<SysOAuthUser> sysOAuthUserRep,
|
||||||
WechatApiClientFactory wechatApiClientFactory)
|
WechatApiClientFactory wechatApiClientFactory)
|
||||||
{
|
{
|
||||||
|
_sysAuthService = sysAuthService;
|
||||||
_sysOAuthUserRep = sysOAuthUserRep;
|
_sysOAuthUserRep = sysOAuthUserRep;
|
||||||
_sysConfigService = sysConfigService;
|
|
||||||
_wechatApiClientFactory = wechatApiClientFactory;
|
_wechatApiClientFactory = wechatApiClientFactory;
|
||||||
_wechatApiClient = wechatApiClientFactory.CreateWechatClient();
|
_wechatApiClient = wechatApiClientFactory.CreateWechatClient();
|
||||||
}
|
}
|
||||||
@ -92,20 +96,14 @@ public class SysWechatService : IDynamicApiController, ITransient
|
|||||||
[DisplayName("微信用户登录OpenId")]
|
[DisplayName("微信用户登录OpenId")]
|
||||||
public async Task<dynamic> OpenIdLogin(WechatUserLogin input)
|
public async Task<dynamic> OpenIdLogin(WechatUserLogin input)
|
||||||
{
|
{
|
||||||
var wxUser = await _sysOAuthUserRep.GetFirstAsync(p => p.OpenId == input.OpenId);
|
var wxUser = await _sysOAuthUserRep.AsQueryable().Includes(u => u.SysUser, u => u.SysOrg).FirstAsync(p => p.OpenId == input.OpenId);
|
||||||
if (wxUser == null)
|
if (wxUser == null) throw Oops.Oh("微信用户登录OpenId错误");
|
||||||
throw Oops.Oh("微信用户登录OpenId错误");
|
if (wxUser.SysUser == null) throw Oops.Oh("微信用户未关联");
|
||||||
|
var tokenInfo = await _sysAuthService.CreateToken(wxUser.SysUser);
|
||||||
var tokenExpire = await _sysConfigService.GetTokenExpire();
|
|
||||||
return new
|
return new
|
||||||
{
|
{
|
||||||
wxUser.Avatar,
|
wxUser.Avatar,
|
||||||
accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
|
accessToken = tokenInfo.AccessToken
|
||||||
{
|
|
||||||
{ ClaimConst.UserId, wxUser.Id },
|
|
||||||
{ ClaimConst.NickName, wxUser.NickName },
|
|
||||||
{ ClaimConst.LoginMode, LoginModeEnum.APP },
|
|
||||||
}, tokenExpire)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,21 +13,22 @@ namespace Admin.NET.Core.Service;
|
|||||||
public class SysWxOpenService : IDynamicApiController, ITransient
|
public class SysWxOpenService : IDynamicApiController, ITransient
|
||||||
{
|
{
|
||||||
private readonly SqlSugarRepository<SysOAuthUser> _sysOAuthUserRep;
|
private readonly SqlSugarRepository<SysOAuthUser> _sysOAuthUserRep;
|
||||||
private readonly SysConfigService _sysConfigService;
|
private readonly SysAuthService _sysAuthService;
|
||||||
private readonly WechatApiClient _wechatApiClient;
|
private readonly WechatApiClient _wechatApiClient;
|
||||||
private readonly SysFileService _sysFileService;
|
private readonly SysFileService _sysFileService;
|
||||||
private readonly WechatApiClientFactory _wechatApiClientFactory;
|
private readonly WechatApiClientFactory _wechatApiClientFactory;
|
||||||
|
|
||||||
public SysWxOpenService(SqlSugarRepository<SysOAuthUser> sysOAuthUserRep,
|
public SysWxOpenService(
|
||||||
SysConfigService sysConfigService,
|
SqlSugarRepository<SysOAuthUser> sysOAuthUserRep,
|
||||||
|
SysAuthService sysAuthService,
|
||||||
WechatApiClientFactory wechatApiClientFactory,
|
WechatApiClientFactory wechatApiClientFactory,
|
||||||
SysFileService sysFileService)
|
SysFileService sysFileService)
|
||||||
{
|
{
|
||||||
_sysOAuthUserRep = sysOAuthUserRep;
|
_sysOAuthUserRep = sysOAuthUserRep;
|
||||||
_sysConfigService = sysConfigService;
|
_sysAuthService = sysAuthService;
|
||||||
_wechatApiClient = wechatApiClientFactory.CreateWxOpenClient();
|
|
||||||
_sysFileService = sysFileService;
|
_sysFileService = sysFileService;
|
||||||
_wechatApiClientFactory = wechatApiClientFactory;
|
_wechatApiClientFactory = wechatApiClientFactory;
|
||||||
|
_wechatApiClient = wechatApiClientFactory.CreateWxOpenClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -119,17 +120,14 @@ public class SysWxOpenService : IDynamicApiController, ITransient
|
|||||||
[DisplayName("微信小程序登录OpenId")]
|
[DisplayName("微信小程序登录OpenId")]
|
||||||
public async Task<dynamic> WxOpenIdLogin(WxOpenIdLoginInput input)
|
public async Task<dynamic> WxOpenIdLogin(WxOpenIdLoginInput input)
|
||||||
{
|
{
|
||||||
var wxUser = await _sysOAuthUserRep.GetFirstAsync(p => p.OpenId == input.OpenId) ?? throw Oops.Oh("微信小程序登录失败");
|
var wxUser = await _sysOAuthUserRep.AsQueryable().Includes(u => u.SysUser, u => u.SysOrg).FirstAsync(p => p.OpenId == input.OpenId) ?? throw Oops.Oh("微信小程序登录失败");
|
||||||
var tokenExpire = await _sysConfigService.GetTokenExpire();
|
if (wxUser.SysUser == null) throw Oops.Oh("微信未关联该用户");
|
||||||
|
|
||||||
|
var tokenInfo = await _sysAuthService.CreateToken(wxUser.SysUser, LoginModeEnum.APP);
|
||||||
return new
|
return new
|
||||||
{
|
{
|
||||||
wxUser.Avatar,
|
wxUser.Avatar,
|
||||||
accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
|
accessToken = tokenInfo.AccessToken
|
||||||
{
|
|
||||||
{ ClaimConst.UserId, wxUser.Id },
|
|
||||||
{ ClaimConst.RealName, wxUser.NickName },
|
|
||||||
{ ClaimConst.LoginMode, LoginModeEnum.APP },
|
|
||||||
}, tokenExpire)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,8 @@ namespace Admin.NET.Core;
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
public class SqlSugarRepository<T> : SimpleClient<T>, ISqlSugarRepository<T> where T : class, new()
|
public class SqlSugarRepository<T> : SimpleClient<T>, ISqlSugarRepository<T> where T : class, new()
|
||||||
{
|
{
|
||||||
|
private static readonly Lazy<UserManager> _userManager = new(() => App.GetService<UserManager>());
|
||||||
|
|
||||||
public SqlSugarRepository()
|
public SqlSugarRepository()
|
||||||
{
|
{
|
||||||
var iTenant = SqlSugarSetup.ITenant;
|
var iTenant = SqlSugarSetup.ITenant;
|
||||||
@ -37,7 +39,7 @@ public class SqlSugarRepository<T> : SimpleClient<T>, ISqlSugarRepository<T> whe
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// 若未贴任何表特性或当前未登录或是默认租户Id,则返回默认库连接
|
// 若未贴任何表特性或当前未登录或是默认租户Id,则返回默认库连接
|
||||||
var tenantId = App.User?.FindFirst(ClaimConst.TenantId)?.Value;
|
var tenantId = _userManager.Value.TenantId?.ToString();
|
||||||
if (string.IsNullOrWhiteSpace(tenantId) || tenantId == SqlSugarConst.MainConfigId) return;
|
if (string.IsNullOrWhiteSpace(tenantId) || tenantId == SqlSugarConst.MainConfigId) return;
|
||||||
|
|
||||||
// 根据租户Id切换库连接, 为空则返回默认库连接
|
// 根据租户Id切换库连接, 为空则返回默认库连接
|
||||||
|
|||||||
@ -212,6 +212,7 @@ public static class SqlSugarSetup
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 数据审计
|
// 数据审计
|
||||||
|
Lazy<UserManager> userManager = new(() => App.GetService<UserManager>());
|
||||||
dbProvider.Aop.DataExecuting = (oldValue, entityInfo) =>
|
dbProvider.Aop.DataExecuting = (oldValue, entityInfo) =>
|
||||||
{
|
{
|
||||||
// 新增/插入 操作
|
// 新增/插入 操作
|
||||||
@ -249,7 +250,7 @@ public static class SqlSugarSetup
|
|||||||
if (entityInfo.PropertyName == nameof(EntityTenantId.TenantId))
|
if (entityInfo.PropertyName == nameof(EntityTenantId.TenantId))
|
||||||
{
|
{
|
||||||
if (entityValue.TenantId == null || entityValue.TenantId == 0)
|
if (entityValue.TenantId == null || entityValue.TenantId == 0)
|
||||||
entityInfo.SetValue(App.User.FindFirst(ClaimConst.TenantId)?.Value ?? SqlSugarConst.DefaultTenantId.ToString());
|
entityInfo.SetValue(userManager.Value.TenantId?.ToString() ?? SqlSugarConst.DefaultTenantId.ToString());
|
||||||
}
|
}
|
||||||
else if (entityInfo.PropertyName == nameof(EntityBase.CreateUserId))
|
else if (entityInfo.PropertyName == nameof(EntityBase.CreateUserId))
|
||||||
{
|
{
|
||||||
@ -259,17 +260,17 @@ public static class SqlSugarSetup
|
|||||||
else if (entityInfo.PropertyName == nameof(EntityBase.CreateUserName))
|
else if (entityInfo.PropertyName == nameof(EntityBase.CreateUserName))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(entityValue.CreateUserName))
|
if (string.IsNullOrWhiteSpace(entityValue.CreateUserName))
|
||||||
entityInfo.SetValue(App.User.FindFirst(ClaimConst.RealName)?.Value);
|
entityInfo.SetValue(userManager.Value.RealName);
|
||||||
}
|
}
|
||||||
else if (entityInfo.PropertyName == nameof(EntityBaseData.CreateOrgId))
|
else if (entityInfo.PropertyName == nameof(EntityBaseData.CreateOrgId))
|
||||||
{
|
{
|
||||||
if (entityValue.CreateOrgId == null || entityValue.CreateOrgId == 0)
|
if (entityValue.CreateOrgId == null || entityValue.CreateOrgId == 0)
|
||||||
entityInfo.SetValue(App.User.FindFirst(ClaimConst.OrgId)?.Value);
|
entityInfo.SetValue(userManager.Value.OrgId);
|
||||||
}
|
}
|
||||||
else if (entityInfo.PropertyName == nameof(EntityBaseData.CreateOrgName))
|
else if (entityInfo.PropertyName == nameof(EntityBaseData.CreateOrgName))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(entityValue.CreateOrgName))
|
if (string.IsNullOrWhiteSpace(entityValue.CreateOrgName))
|
||||||
entityInfo.SetValue(App.User.FindFirst(ClaimConst.OrgName)?.Value);
|
entityInfo.SetValue(userManager.Value.OrgName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 编辑/更新 操作
|
// 编辑/更新 操作
|
||||||
@ -280,7 +281,7 @@ public static class SqlSugarSetup
|
|||||||
else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserId))
|
else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserId))
|
||||||
entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value);
|
entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value);
|
||||||
else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserName))
|
else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserName))
|
||||||
entityInfo.SetValue(App.User?.FindFirst(ClaimConst.RealName)?.Value);
|
entityInfo.SetValue(userManager.Value.RealName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置绑定简称字段数据
|
// 设置绑定简称字段数据
|
||||||
@ -294,14 +295,14 @@ public static class SqlSugarSetup
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 超管不受任何过滤器限制
|
// 超管不受任何过滤器限制
|
||||||
if (App.User?.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString())
|
if (userManager.Value.AccountType?.ToString() == ((int)AccountTypeEnum.SuperAdmin).ToString())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 配置假删除过滤器
|
// 配置假删除过滤器
|
||||||
dbProvider.QueryFilter.AddTableFilter<IDeletedFilter>(u => u.IsDelete == false);
|
dbProvider.QueryFilter.AddTableFilter<IDeletedFilter>(u => u.IsDelete == false);
|
||||||
|
|
||||||
// 配置租户过滤器
|
// 配置租户过滤器
|
||||||
var tenantId = App.User?.FindFirst(ClaimConst.TenantId)?.Value;
|
var tenantId = userManager.Value.TenantId?.ToString();
|
||||||
if (!string.IsNullOrWhiteSpace(tenantId))
|
if (!string.IsNullOrWhiteSpace(tenantId))
|
||||||
dbProvider.QueryFilter.AddTableFilter<ITenantIdFilter>(u => u.TenantId == long.Parse(tenantId));
|
dbProvider.QueryFilter.AddTableFilter<ITenantIdFilter>(u => u.TenantId == long.Parse(tenantId));
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ namespace Admin.NET.Web.Core
|
|||||||
public class JwtHandler : AppAuthorizeHandler
|
public class JwtHandler : AppAuthorizeHandler
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private static readonly Lazy<UserManager> _userManager = new(() => App.GetService<UserManager>());
|
||||||
|
|
||||||
public JwtHandler(IServiceProvider serviceProvider)
|
public JwtHandler(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
@ -59,7 +60,8 @@ namespace Admin.NET.Web.Core
|
|||||||
|
|
||||||
// 验证Token黑名单
|
// 验证Token黑名单
|
||||||
var accessToken = httpContext.Request.Headers.Authorization.ToString();
|
var accessToken = httpContext.Request.Headers.Authorization.ToString();
|
||||||
if (sysCacheService.ExistKey($"{CacheConst.KeyTokenBlacklist}:{accessToken}"))
|
var userId = httpContext.User.FindFirst(ClaimConst.UserId)?.Value;
|
||||||
|
if (sysCacheService.ExistKey($"{CacheConst.KeyTokenBlacklist}:{accessToken}") || !sysCacheService.ExistKey($"{CacheConst.KeyUserSession}{userId}"))
|
||||||
{
|
{
|
||||||
context.Fail(new AuthorizationFailureReason(this, "令牌已失效,请重新登录。"));
|
context.Fail(new AuthorizationFailureReason(this, "令牌已失效,请重新登录。"));
|
||||||
context.GetCurrentHttpContext().SignoutToSwagger();
|
context.GetCurrentHttpContext().SignoutToSwagger();
|
||||||
@ -67,7 +69,6 @@ namespace Admin.NET.Web.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证Token版本号
|
// 验证Token版本号
|
||||||
var userId = httpContext.User.FindFirst(ClaimConst.UserId)?.Value;
|
|
||||||
var tokenVersion1 = httpContext.User.FindFirst(ClaimConst.TokenVersion)?.Value;
|
var tokenVersion1 = httpContext.User.FindFirst(ClaimConst.TokenVersion)?.Value;
|
||||||
var tokenVersion2 = sysCacheService.Get<string>($"{CacheConst.KeyUserToken}{userId}");
|
var tokenVersion2 = sysCacheService.Get<string>($"{CacheConst.KeyUserToken}{userId}");
|
||||||
if (string.IsNullOrWhiteSpace(tokenVersion2) && !string.IsNullOrWhiteSpace(userId))
|
if (string.IsNullOrWhiteSpace(tokenVersion2) && !string.IsNullOrWhiteSpace(userId))
|
||||||
@ -91,7 +92,7 @@ namespace Admin.NET.Web.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证租户有效期
|
// 验证租户有效期
|
||||||
var tenantId = httpContext.User.FindFirst(ClaimConst.TenantId)?.Value;
|
var tenantId = _userManager.Value.TenantId?.ToString();
|
||||||
if (!string.IsNullOrWhiteSpace(tenantId))
|
if (!string.IsNullOrWhiteSpace(tenantId))
|
||||||
{
|
{
|
||||||
var tenant = sysCacheService.Get<List<SysTenant>>(CacheConst.KeyTenant)?.FirstOrDefault(u => u.Id == long.Parse(tenantId));
|
var tenant = sysCacheService.Get<List<SysTenant>>(CacheConst.KeyTenant)?.FirstOrDefault(u => u.Id == long.Parse(tenantId));
|
||||||
@ -117,7 +118,7 @@ namespace Admin.NET.Web.Core
|
|||||||
private static async Task<bool> CheckAuthorizeAsync(DefaultHttpContext httpContext)
|
private static async Task<bool> CheckAuthorizeAsync(DefaultHttpContext httpContext)
|
||||||
{
|
{
|
||||||
// 排除超管权限判断
|
// 排除超管权限判断
|
||||||
if (App.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString())
|
if (_userManager.Value?.AccountType == AccountTypeEnum.SuperAdmin)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var serviceScope = httpContext.RequestServices.CreateScope();
|
var serviceScope = httpContext.RequestServices.CreateScope();
|
||||||
@ -126,7 +127,7 @@ namespace Admin.NET.Web.Core
|
|||||||
var path = httpContext.Request.Path.ToString();
|
var path = httpContext.Request.Path.ToString();
|
||||||
|
|
||||||
// 移动端接口权限判断
|
// 移动端接口权限判断
|
||||||
if (App.User.FindFirst(ClaimConst.LoginMode)?.Value == ((int)LoginModeEnum.APP).ToString())
|
if (_userManager.Value?.LoginMode == LoginModeEnum.APP)
|
||||||
{
|
{
|
||||||
var appApiList = serviceScope.ServiceProvider.GetRequiredService<SysCommonService>().GetAppApiList();
|
var appApiList = serviceScope.ServiceProvider.GetRequiredService<SysCommonService>().GetAppApiList();
|
||||||
return appApiList.Exists(u => path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase));
|
return appApiList.Exists(u => path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|||||||
@ -37,7 +37,7 @@ namespace @Model.NameSpace;
|
|||||||
public partial class @(@Model.ClassName)Service : IDynamicApiController, ITransient
|
public partial class @(@Model.ClassName)Service : IDynamicApiController, ITransient
|
||||||
{
|
{
|
||||||
private readonly SysCacheService _sysCacheService;//默认CacheService
|
private readonly SysCacheService _sysCacheService;//默认CacheService
|
||||||
private readonly UserManager _userManager;//默认用户管理
|
private readonly UserSession _userManager;//默认用户管理
|
||||||
private readonly IEventPublisher _eventPublisher;//默认事件总线
|
private readonly IEventPublisher _eventPublisher;//默认事件总线
|
||||||
private readonly SqlSugarRepository<@(@Model.ClassName)> _@(@Model.LowerClassName)Rep;
|
private readonly SqlSugarRepository<@(@Model.ClassName)> _@(@Model.LowerClassName)Rep;
|
||||||
@foreach (var column in Model.TableField){
|
@foreach (var column in Model.TableField){
|
||||||
@ -51,7 +51,7 @@ public partial class @(@Model.ClassName)Service : IDynamicApiController, ITransi
|
|||||||
|
|
||||||
public @(@Model.ClassName)Service(SqlSugarRepository<@(@Model.ClassName)> @(@Model.LowerClassName)Rep
|
public @(@Model.ClassName)Service(SqlSugarRepository<@(@Model.ClassName)> @(@Model.LowerClassName)Rep
|
||||||
,SysCacheService sysCacheService
|
,SysCacheService sysCacheService
|
||||||
, UserManager userManager
|
, UserSession userManager
|
||||||
,IEventPublisher eventPublisher
|
,IEventPublisher eventPublisher
|
||||||
@foreach (var column in Model.TableField){
|
@foreach (var column in Model.TableField){
|
||||||
if(@column.EffectType == "ForeignKey"||@column.EffectType == "ApiTreeSelector"){
|
if(@column.EffectType == "ForeignKey"||@column.EffectType == "ApiTreeSelector"){
|
||||||
|
|||||||
@ -18,6 +18,7 @@ namespace Admin.NET.Plugin.ReZero.Service;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SuperApiAop : DefaultSuperApiAop
|
public class SuperApiAop : DefaultSuperApiAop
|
||||||
{
|
{
|
||||||
|
private static readonly Lazy<UserManager> _userManager = new(() => App.GetService<UserManager>());
|
||||||
public override async Task OnExecutingAsync(InterfaceContext aopContext)
|
public override async Task OnExecutingAsync(InterfaceContext aopContext)
|
||||||
{
|
{
|
||||||
////if (aopContext.InterfaceType == InterfaceType.DynamicApi)
|
////if (aopContext.InterfaceType == InterfaceType.DynamicApi)
|
||||||
@ -59,13 +60,6 @@ public class SuperApiAop : DefaultSuperApiAop
|
|||||||
var api = aopContext.InterfaceInfo;
|
var api = aopContext.InterfaceInfo;
|
||||||
var context = aopContext.HttpContext;
|
var context = aopContext.HttpContext;
|
||||||
|
|
||||||
var accessToken = context.Request.Headers.Authorization.ToString();
|
|
||||||
if (!string.IsNullOrWhiteSpace(accessToken) && accessToken.StartsWith("Bearer "))
|
|
||||||
accessToken = accessToken.Replace("Bearer ", "");
|
|
||||||
var claims = JWTEncryption.ReadJwtToken(accessToken)?.Claims;
|
|
||||||
var userName = claims?.FirstOrDefault(u => u.Type == ClaimConst.Account)?.Value;
|
|
||||||
var realName = claims?.FirstOrDefault(u => u.Type == ClaimConst.RealName)?.Value;
|
|
||||||
|
|
||||||
var paths = api.Url.Split('/');
|
var paths = api.Url.Split('/');
|
||||||
var actionName = paths[paths.Length - 1];
|
var actionName = paths[paths.Length - 1];
|
||||||
|
|
||||||
@ -86,13 +80,13 @@ public class SuperApiAop : DefaultSuperApiAop
|
|||||||
{
|
{
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
type = ClaimConst.Account,
|
type = _userManager.Value?.Account,
|
||||||
value = userName
|
value = _userManager.Value?.RealName
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
type = ClaimConst.RealName,
|
type = _userManager.Value?.RealName,
|
||||||
value = realName
|
value = _userManager.Value?.RealName
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
exception = aopContext.Exception == null ? null : JSON.Serialize(aopContext.Exception)
|
exception = aopContext.Exception == null ? null : JSON.Serialize(aopContext.Exception)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user