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());
}
}
}