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.Extensions; using VOL.Core.Extensions.AutofacManager; 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).Result; } } private UserInfo _userInfo { get; set; } /// /// 角色ID为1的默认为超级管理员 /// public bool IsSuperAdmin { get { return this.RoleId == 1; } } /// /// 角色ID为1的默认为超级管理员 /// public static bool IsRoleIdSuperAdmin(int roleId) { return roleId == 1; } public async Task 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 = await DBServerProvider.DbContext.Set() .Where(x => x.User_Id == userId).Select(s => new UserInfo() { User_Id = userId, Role_Id = s.Role_Id.GetInt(), RoleName = s.RoleName, Token = s.Token, UserName = s.UserName, UserTrueName = s.UserTrueName, Enable = s.Enable }).FirstOrDefaultAsync(); if (_userInfo != null && _userInfo.User_Id > 0) { CacheService.AddObject(key, _userInfo); } return _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); } } /// /// 获取单个表的权限 /// /// /// public Permissions GetPermissions(string tableName) { return GetPermissions(RoleId).Where(x => x.TableName == tableName).FirstOrDefault(); } /// /// 自定条件查询权限 /// /// /// public Permissions GetPermissions(Func func) { return GetPermissions(RoleId).Where(func).FirstOrDefault(); } private List ActionToArray(List permissions) { permissions.ForEach(x => { try { x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth) ? new string[0] : x.UserAuth.Split(","); } 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)) { var permissions = DBServerProvider.DbContext.Set().Where(x => x.Enable == 1).Select(a => new Permissions { Menu_Id = a.Menu_Id, ParentId = a.ParentId, TableName = a.TableName ?? "", //MenuAuth = a.Auth, UserAuth = a.Auth, }).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, TableName = a.TableName ?? "", MenuAuth = a.Auth, UserAuth = b.AuthValue ?? "" }).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(); authName = authName.ToLower(); return GetPermissions(roleId).Any(x => x.TableName == tableName && x.UserAuthArr.Contains(authName)); } public int UserId { get { // if (!Context.User.Identity.IsAuthenticated) return 0; 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 void LogOut(int userId) { CacheService.Remove(userId.GetUserIdKey()); } } }