using Microsoft.EntityFrameworkCore; 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 VOL.Core.CacheManager; using VOL.Core.DBManager; using VOL.Core.Enums; using VOL.Core.Extensions; using VOL.Core.Extensions.AutofacManager; using VOL.Core.UserManager; using VOL.Entity; using VOL.Entity.DomainModels; namespace VOL.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.RoleId); } } /// /// 角色ID为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(); 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.GetInt(), RoleName = s.RoleName, //2022.08.15增加部门id DeptId = s.Dept_Id??0, Token = s.Token, UserName = s.UserName, UserTrueName = s.UserTrueName, Enable = s.Enable, DeptIds= s.DeptIds }).ToList().Select(s => new UserInfo() { User_Id = userId, Role_Id = s.Role_Id, Token = s.Token, UserName = s.UserName, UserTrueName = s.UserTrueName, Enable = 1, DeptIds = string.IsNullOrEmpty(s.DeptIds) ? new List() : s.DeptIds.Split(",").Select(x => (Guid)x.GetGuid()).ToList(), }).FirstOrDefault(); if (_userInfo != null && _userInfo.User_Id > 0) { CacheService.AddObject(key, _userInfo); } return _userInfo ?? new UserInfo(); } /// /// 获取角色权限时通过安全字典锁定的角色id /// private static ConcurrentDictionary objKeyValue = new ConcurrentDictionary(); /// /// 角色权限的版本号 /// private static readonly Dictionary rolePermissionsVersion = new Dictionary(); /// /// 每个角色ID对应的菜单权限(已做静态化处理) /// 每次获取权限时用当前服务器的版本号与redis/memory缓存的版本比较,如果不同会重新刷新缓存 /// private static readonly Dictionary> rolePermissions = new Dictionary>(); /// /// 获取用户所有的菜单权限 /// public List Permissions { get { return GetPermissions(RoleId); } } /// /// 菜单按钮变更时,同时刷新权限缓存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(RoleId).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(RoleId).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 roleId) { if (IsRoleIdSuperAdmin(roleId)) { //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; string roleKey = roleId.GetRoleIdKey(); //角色有缓存,并且当前服务器的角色版本号与redis/memory缓存角色的版本号相同直接返回静态对象角色权限 string currnetVeriosn = ""; if (rolePermissionsVersion.TryGetValue(roleId, out currnetVeriosn) && currnetVeriosn == cacheService.Get(roleKey)) { 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)) { return rolePermissions.ContainsKey(roleId) ? rolePermissions[roleId] : new List(); } //没有redis/memory缓存角色的版本号或与当前服务器的角色版本号不同时,刷新缓存 var dbContext = DBServerProvider.DbContext; 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(); 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 _permissions; } } /// /// 判断是否有权限 /// /// /// /// /// public bool ExistsPermissions(string tableName, string authName, int roleId = 0) { if (roleId <= 0) roleId = RoleId; tableName = tableName.ToLower(); return GetPermissions(roleId).Any(x => x.TableName == tableName && x.UserAuthArr.Contains(authName)); } /// /// 判断是否有权限 /// /// /// /// /// public bool ExistsPermissions(string tableName, ActionPermissionOptions actionPermission, int roleId = 0) { return ExistsPermissions(tableName, actionPermission.ToString(), roleId); } 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 RoleId { get { return UserInfo.Role_Id; } } public List DeptIds { get { return UserInfo.DeptIds; } } /// /// 获取所有子部门 /// /// public List GetAllChildrenDeptIds() { return DepartmentContext.GetAllChildrenIds(DeptIds); } public void LogOut(int userId) { CacheService.Remove(userId.GetUserIdKey()); } } }