using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Primitives; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using VolPro.Core.CacheManager; using VolPro.Core.DBManager; using VolPro.Core.DbSqlSugar; using VolPro.Core.Enums; using VolPro.Core.Extensions; using VolPro.Core.Extensions.AutofacManager; using VolPro.Core.UserManager; using VolPro.Entity; using VolPro.Entity.DomainModels; namespace VolPro.Core.ManageUser { public class UserContext { /// /// 为了尽量减少redis或Memory读取,保证执行效率,将UserContext注入到DI, /// 每个UserContext的属性至多读取一次redis或Memory缓存从而提高查询效率 /// public static UserContext Current { get { return Context.RequestServices.GetService(typeof(UserContext)) as UserContext; } } private static Microsoft.AspNetCore.Http.HttpContext Context { get { return Utilities.HttpContext.Current; } } private static ICacheService CacheService { get { return GetService(); } } private static T GetService() where T : class { return AutofacContainerModule.GetService(); } public UserInfo UserInfo { get { if (_userInfo != null) { return _userInfo; } return GetUserInfo(UserId); } } private UserInfo _userInfo { get; set; } /// /// 角色ID为1的默认为超级管理员 /// public bool IsSuperAdmin { get { return IsRoleIdSuperAdmin(this.RoleIds); } } /// /// 角色ID为1的默认为超级管理员 /// public static bool IsRoleIdSuperAdmin(int[] roleIds) { return roleIds.Contains(1); } public static bool IsRoleIdSuperAdmin(int roleId) { return roleId == 1; } public UserInfo GetUserInfo(int userId) { if (_userInfo != null) return _userInfo; if (userId <= 0) { _userInfo = new UserInfo() { RoleIds = new int[] { } }; return _userInfo; } string key = userId.GetUserIdKey(); _userInfo = CacheService.Get(key); if (_userInfo != null && _userInfo.User_Id > 0) return _userInfo; _userInfo = DBServerProvider.DbContext.Set() .Where(x => x.User_Id == userId).Select(s => new { User_Id = userId, Role_Id = s.Role_Id ?? 0, Token = s.Token, UserName = s.UserName, UserTrueName = s.UserTrueName, Enable = 1, s.RoleIds, s.DeptIds, s.PostId }).ToList().Select(s => new UserInfo() { User_Id = userId, Role_Id = s.Role_Id, Token = s.Token, UserName = s.UserName, UserTrueName = s.UserTrueName, Enable = 1, RoleIds = s.Role_Id == 1 ? new int[] { 1 } : (string.IsNullOrEmpty(s.RoleIds) ? new int[] { } : s.RoleIds.Split(",").Select(x => x.GetInt()).ToArray()), DeptIds = string.IsNullOrEmpty(s.DeptIds) ? new List() : s.DeptIds.Split(",").Select(x => (Guid)x.GetGuid()).ToList(), PostIds = string.IsNullOrEmpty(s.PostId) ? new List() : s.PostId.Split(",").Select(x => (Guid)x.GetGuid()).ToList(), TenancyValue = null //用户租户字段请在此处返回实现 }).FirstOrDefault(); if (_userInfo != null && _userInfo.User_Id > 0) { CacheService.AddObject(key, _userInfo); } return _userInfo ?? new UserInfo() { RoleIds = new int[] { } }; } /// /// 获取角色权限时通过安全字典锁定的角色id /// private static ConcurrentDictionary objKeyValue = new ConcurrentDictionary(); /// /// 角色权限的版本号 /// private static readonly Dictionary rolePermissionsVersion = new Dictionary(); /// /// 每个角色ID对应的菜单权限(已做静态化处理) /// 每次获取权限时用当前服务器的版本号与redis/memory缓存的版本比较,如果不同会重新刷新缓存 /// private static readonly Dictionary> rolePermissions = new Dictionary>(); private static ConcurrentDictionary objUserValue = new ConcurrentDictionary(); private static readonly Dictionary userAuthVersion = new Dictionary(); private static readonly Dictionary> userAuthPermissions = new Dictionary>(); /// /// 获取用户所有的菜单权限 /// public List Permissions { get { return GetPermissions(RoleIds); } } /// /// 菜单按钮变更时,同时刷新权限缓存2022.05.23 /// /// public void RefreshWithMenuActionChange(int menuId) { foreach (var roleId in rolePermissions.Where(c => c.Value.Any(x => x.Menu_Id == menuId)).Select(s => s.Key)) { if (rolePermissionsVersion.ContainsKey(roleId)) { CacheService.Add(roleId.GetRoleIdKey(), DateTime.Now.ToString("yyyyMMddHHMMssfff")); } } } /// /// 获取单个表的权限 /// /// /// public Permissions GetPermissions(string tableName) { return GetPermissions(RoleIds).Where(x => x.TableName == tableName).FirstOrDefault(); } /// /// 2022.03.26 /// 菜单类型1:移动端,0:PC端 /// public static int MenuType { get { return Context.Request.Headers.ContainsKey("uapp") ? 1 : 0; } } /// /// 自定条件查询权限 /// /// /// public Permissions GetPermissions(Func func) { // 2022.03.26增移动端加菜单类型判断 return GetPermissions(RoleIds).Where(func).Where(x => x.MenuType == MenuType).FirstOrDefault(); } private List ActionToArray(List permissions) { permissions.ForEach(x => { try { var menuAuthArr = x.MenuAuth.DeserializeObject>(); x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth) ? new string[0] : x.UserAuth.Split(",").Where(c => menuAuthArr.Any(m => m.Value == c)).ToArray(); } catch { } finally { if (x.UserAuthArr == null) { x.UserAuthArr = new string[0]; } } }); return permissions; } private List MenuActionToArray(List permissions) { permissions.ForEach(x => { try { x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth) ? new string[0] : x.UserAuth.DeserializeObject>().Select(s => s.Value).ToArray(); } catch { } finally { if (x.UserAuthArr == null) { x.UserAuthArr = new string[0]; } } }); return permissions; } /// /// 用户菜单权限 /// /// /// public List GetPermissions(int[] roleIds) { if (IsRoleIdSuperAdmin(roleIds)) { //2020.12.27增加菜单界面上不显示,但可以分配权限 var permissions = DBServerProvider.DbContext.Set() .Where(x => x.Enable == 1 || x.Enable == 2) .Select(a => new Permissions { Menu_Id = a.Menu_Id, ParentId = a.ParentId, //2020.05.06增加默认将表名转换成小写,权限验证时不再转换 TableName = (a.TableName ?? "").ToLower(), //MenuAuth = a.Auth, UserAuth = a.Auth, // 2022.03.26增移动端加菜单类型 MenuType = a.MenuType ?? 0 }).ToList(); return MenuActionToArray(permissions); } ICacheService cacheService = CacheService; for (int i = 0; i < roleIds.Length; i++) { int roleId = roleIds[i]; string roleKey = roleId.GetRoleIdKey(); //角色有缓存,并且当前服务器的角色版本号与redis/memory缓存角色的版本号相同直接返回静态对象角色权限 string currnetVeriosn = ""; if (rolePermissionsVersion.TryGetValue(roleId, out currnetVeriosn) && currnetVeriosn == cacheService.Get(roleKey)) { continue; //return rolePermissions.ContainsKey(roleId) ? rolePermissions[roleId] : new List(); } //锁定每个角色,通过安全字典减少锁粒度,否则多个同时角色获取缓存会导致阻塞 object objId = objKeyValue.GetOrAdd(roleId.ToString(), new object()); //锁定每个角色 lock (objId) { if (rolePermissionsVersion.TryGetValue(roleId, out currnetVeriosn) && currnetVeriosn == cacheService.Get(roleKey)) { continue; // return rolePermissions.ContainsKey(roleId) ? rolePermissions[roleId] : new List(); } //没有redis/memory缓存角色的版本号或与当前服务器的角色版本号不同时,刷新缓存 var dbContext = DBServerProvider.DbContext; // var query5 = db.Queryable() //.LeftJoin((o, cus) => o.CustomId == cus.Id)//多个条件用&& //.LeftJoin((o, cus, oritem) => o.Id == oritem.OrderId) //.Where(o => o.Id == 1) //.Select((o, cus, oritem) => new ViewOrder { Id = o.Id, CustomName = cus.Name }) //.ToList(); //ViewOrder是一个新建的类,更多Select用法看下面文档 List _permissions = dbContext.SqlSugarClient.Queryable() .LeftJoin((a, b) => a.Menu_Id == b.Menu_Id) .Where((a, b) => b.Role_Id == roleId && b.AuthValue != "") .OrderBy(a => a.ParentId) .Select((a, b) => new Permissions { Menu_Id = a.Menu_Id, ParentId = a.ParentId, //2020.05.06增加默认将表名转换成小写,权限验证时不再转换 TableName = (a.TableName ?? "").ToLower(), MenuAuth = a.Auth, UserAuth = b.AuthValue ?? "", //2024.08.11增加菜单数据权限 AuthMenuData = b.AuthMenuData, // 2022.03.26增移动端加菜单类型 MenuType = a.MenuType ?? 0 }).ToList(); //List _permissions = (from a in dbContext.Set() // join b in dbContext.Set() // on a.Menu_Id equals b.Menu_Id // where b.Role_Id == roleId //&& a.ParentId > 0 // && b.AuthValue != "" // orderby a.ParentId // select new Permissions // { // Menu_Id = a.Menu_Id, // ParentId = a.ParentId, // //2020.05.06增加默认将表名转换成小写,权限验证时不再转换 // TableName = (a.TableName ?? "").ToLower(), // MenuAuth = a.Auth, // UserAuth = b.AuthValue ?? "", // // 2022.03.26增移动端加菜单类型 // MenuType = a.MenuType ?? 0 // }).ToList(); // }).ToList(); ActionToArray(_permissions); string _version = cacheService.Get(roleKey); //生成一个唯一版本号标识 if (_version == null) { _version = DateTime.Now.ToString("yyyyMMddHHMMssfff"); //将版本号写入缓存 cacheService.Add(roleKey, _version); } //刷新当前服务器角色的权限 rolePermissions[roleId] = _permissions; //写入当前服务器的角色最新版本号 rolePermissionsVersion[roleId] = _version; } } return rolePermissions.Where(x => roleIds.Contains(x.Key)) .SelectMany(s => s.Value) .GroupBy(g => g.Menu_Id) .Select(s => new Permissions() { Menu_Id = s.Key, ParentId = s.Select(s1 => s1.ParentId).FirstOrDefault(), TableName = s.Select(s1 => s1.TableName).FirstOrDefault(), MenuType = s.Select(c => c.MenuType).FirstOrDefault(), UserAuthArr = s.SelectMany(s1 => s1.UserAuthArr).ToArray(), //2024.08.11增加菜单数据权限 AuthMenuData = s.Select(s1 => s1.AuthMenuData).FirstOrDefault() }).ToList(); } /// /// 获取用户的表的能看到的数据用户id /// /// /// public int[] GetCurrentUserAuthUserIds(string tableName) { return GetUserAuthData(UserId)?.Where(x => x.TableName == tableName.ToLower())?.FirstOrDefault()?.UserIds; } public List CurrentUserAuthUserIds { get { return GetUserAuthData(UserId); } } public void RemoveUserAuthData(int userId) { userAuthVersion.Remove(userId); } /// /// 用户指定可以看到的某些用户的数据权限 /// /// /// public List GetUserAuthData(int userId) { if (userId <= 0) return null; string currnetVeriosn = ""; string authKey = $"uh:{userId}"; ICacheService cacheService = CacheService; if (!(userAuthVersion.TryGetValue(userId, out currnetVeriosn) && currnetVeriosn == cacheService.Get(authKey))) { object objId = objUserValue.GetOrAdd(userId, new object()); //锁定用户 lock (objId) { if (!((userAuthVersion.TryGetValue(userId, out currnetVeriosn) && currnetVeriosn == cacheService.Get(authKey)))) { // var menuQuery = DBServerProvider.DbContext.Set(); var authQuery = DbManger.SysDbContext.Queryable() .Where(x => x.UserId == userId && x.AuthUserIds != "") .Select(s => new { s.UserId, s.AuthUserIds, s.MenuId, TableName = SqlSugar.SqlFunc.Subqueryable().Where(x => x.Menu_Id == s.MenuId).Select(x => x.TableName) }); var authData = authQuery.ToList().Select(s => new UserAuthData() { UserIds = s.AuthUserIds.Split(",").Select(x => x.GetInt()).ToArray(), Menu_Id = s.MenuId ?? 0, TableName = s.TableName?.ToLower() }).ToList(); string _version = cacheService.Get(authKey); //生成一个唯一版本号标识 if (_version == null) { _version = DateTime.Now.ToString("yyyyMMddHHMMssfff"); //将版本号写入缓存 cacheService.Add(authKey, _version); } //刷新当前服务器角色的权限 userAuthPermissions[userId] = authData; //写入当前服务器的角色最新版本号 userAuthVersion[userId] = _version; return authData; } } } return userAuthPermissions[userId]; } /// /// 判断是否有权限 /// /// /// /// /// public bool ExistsPermissions(string tableName, string authName, int[] roleIds) { if (roleIds == null || roleIds.Length == 0) { return false; }; tableName = tableName.ToLower(); return GetPermissions(roleIds).Any(x => x.TableName == tableName && x.UserAuthArr.Contains(authName)); } /// /// 判断是否有权限 /// /// /// /// /// public bool ExistsPermissions(string tableName, ActionPermissionOptions actionPermission, int[] roleIds) { return ExistsPermissions(tableName, actionPermission.ToString(), roleIds); } public int UserId { get { return (Context.User.FindFirstValue(JwtRegisteredClaimNames.Jti) ?? Context.User.FindFirstValue(ClaimTypes.NameIdentifier)).GetInt(); } } public string UserName { get { return UserInfo.UserName; } } public string UserTrueName { get { return UserInfo.UserTrueName; } } public string Token { get { return UserInfo.Token; } } public int[] RoleIds { get { return UserInfo.RoleIds; } } public List DeptIds { get { return UserInfo.DeptIds; } } /// /// 获取所有子角色包括自己 /// /// public List GetAllChildrenRoleIds() { return RoleContext.GetAllChildrenIds(RoleIds); } /// /// 获取所有子部门 /// /// public List GetAllChildrenDeptIds() { return DepartmentContext.GetAllChildrenIds(DeptIds); } public void LogOut(int userId) { CacheService.Remove(userId.GetUserIdKey()); } /// /// 当前选中的数据库 /// public static Guid CurrentServiceId { get { if (Context.Request.Headers.TryGetValue("serviceId", out StringValues value)) { var val = value.GetGuid() ?? Guid.NewGuid(); if (Current.IsSuperAdmin) { return val; } var roleIds = Current.RoleIds; if (RoleContext.GetRoles(x => roleIds.Contains(x.Id)).Any(x => x.DbServiceId == val)) { return val; } } //2023.12.28优化移动端租户选择 if (Current.RoleIds != null && Current.RoleIds.Length > 0) { return RoleContext.GetRoles(x => Current.RoleIds.Contains(x.Id)).Select(s => s.DbServiceId).FirstOrDefault(); } return Guid.Empty; } } /// /// 当前选中的部门库 /// public static Guid CurrentDeptId { get { if (Context.Request.Headers.TryGetValue("deptId", out StringValues value)) { var val = value.GetGuid() ?? Guid.NewGuid(); //if (Current.IsSuperAdmin) //{ return val; //} //var roleIds = Current.RoleIds; //if (RoleContext.GetRoles(x => roleIds.Contains(x.Id)).Any(x => x.DbServiceId == val)) //{ // return val; //} } return Guid.Empty; } } /// /// 获取用户所有数据库 /// public IEnumerable UserDbService { get { if (IsSuperAdmin) { return DbCache.GetDbInfo(x => true); } var roleIds = RoleIds; var dbIds = RoleContext.GetRoles(x => roleIds.Contains(x.Id)).Select(s => s.DbServiceId).ToList(); return DbCache.GetDbInfo(x => dbIds.Contains(x.DbServiceId));//.Select(s => new { s.DbServiceName, s.DbServiceId }); } } /// 获取租户下的所有用户 /// /// /// public SqlSugar.ISugarQueryable GetQueryableTenancyUser(Guid dbServiceId) { var roleIds = RoleContext.GetRoles(x => x.DbServiceId == dbServiceId).Select(s => s.Id); return DBServerProvider.DbContext.Set().Where(x => x.Enable == 1 && x.RoleId > 1 && roleIds.Contains(x.RoleId)). Select(s => s.UserId); } /// /// 获取指定租户下的所有用户id /// /// /// public List GetTenancyUserId(Guid dbServiceId) { return GetQueryableTenancyUser(dbServiceId).ToList(); } /// /// 获取当前租户下的所有用户id /// public List GetCurrentTenancyUserId { get { return GetQueryableTenancyUser(CurrentServiceId).ToList(); } } /// /// 获取所有子角色下的用户 /// /// 只获取当前角色下的用户(不包括子角色) /// public SqlSugar.ISugarQueryable GetAllChildrenRoleIdUserIds(bool isCurrent) { var roleIds = isCurrent ? RoleIds.ToList() : GetAllChildrenRoleIds(); return DBServerProvider.DbContext.Set().Where(x => x.Enable == 1 && roleIds.Contains(x.RoleId)) .Select(s => s.UserId); } /// /// 获取指定用户所有子角色下的用户 /// /// 只获取当前角色下的用户(不包括子角色) /// public SqlSugar.ISugarQueryable GetUserChildrenRoleIdUserIds(int userId) { var roleIds = DBServerProvider.DbContext.Set().Where(x => x.UserId == userId && x.Enable == 1).Select(s => s.RoleId).ToArray(); var childRoleIds= RoleContext.GetAllChildrenIds(roleIds).ToList(); return DBServerProvider.DbContext.Set().Where(x => x.Enable == 1 && childRoleIds.Contains(x.RoleId)) .Select(s => s.UserId); } } public class UserAuthData { /// /// 当前用户指定的可以看到的用户数据 /// public int[] UserIds { get; set; } public int Menu_Id { get; set; } public string TableName { get; set; } /// /// 2022.03.26 /// 菜单类型1:移动端,0:PC端 /// public int MenuType { get; set; } } }