|
|
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.Entity;
|
|
|
using VOL.Entity.DomainModels;
|
|
|
using ConvertHelper;
|
|
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
|
|
|
|
|
namespace VOL.Core.ManageUser
|
|
|
{
|
|
|
public class UserContext
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 为了尽量减少redis或Memory读取,保证执行效率,将UserContext注入到DI,
|
|
|
/// 每个UserContext的属性至多读取一次redis或Memory缓存从而提高查询效率
|
|
|
/// </summary>
|
|
|
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<ICacheService>(); }
|
|
|
}
|
|
|
|
|
|
private static T GetService<T>() where T : class
|
|
|
{
|
|
|
return AutofacContainerModule.GetService<T>();
|
|
|
}
|
|
|
|
|
|
public UserInfo UserInfo
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
if (_userInfo != null)
|
|
|
{
|
|
|
return _userInfo;
|
|
|
}
|
|
|
return GetUserInfo(UserId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private UserInfo _userInfo { get; set; }
|
|
|
|
|
|
private const string AdministratorId= "1BEC90E1-9780-472F-90C2-0C6390C044A4";
|
|
|
/// <summary>
|
|
|
/// 角色ID为1的默认为超级管理员
|
|
|
/// </summary>
|
|
|
public bool IsSuperAdmin
|
|
|
{
|
|
|
get { return IsRoleIdSuperAdmin(this.RoleId); }
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 角色ID为1的默认为超级管理员
|
|
|
/// </summary>
|
|
|
public static bool IsRoleIdSuperAdmin(string roleId)
|
|
|
{
|
|
|
return roleId == "1";
|
|
|
}
|
|
|
|
|
|
|
|
|
public UserInfo GetUserInfo(Guid userId)
|
|
|
{
|
|
|
if (_userInfo != null) return _userInfo;
|
|
|
if (userId.isNullorEmpty())
|
|
|
{
|
|
|
_userInfo = new UserInfo();
|
|
|
return _userInfo;
|
|
|
}
|
|
|
string key = userId.GetUserIdKey();
|
|
|
|
|
|
_userInfo = CacheService.Get<UserInfo>(key);
|
|
|
if (_userInfo != null && !_userInfo.User_Id.isNullorEmpty() ) return _userInfo;
|
|
|
|
|
|
_userInfo = DBServerProvider.DbContext.Set<Sys_User>()
|
|
|
.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,
|
|
|
CompanyId=s.CompanyId,
|
|
|
Dept_Id=s.Dept_Id,
|
|
|
CompanyName=s.CompanyName
|
|
|
}).FirstOrDefault();
|
|
|
|
|
|
var currrole = DBServerProvider.DbContext.Set<Sys_Role>().First(x => x.Role_Id == _userInfo.Role_Id);
|
|
|
|
|
|
_userInfo.LimitInCompany = currrole.LimitCompanyRange==null?true:(bool)currrole.LimitCompanyRange;
|
|
|
|
|
|
_userInfo.LimitBySTORAGE = currrole.LimitBySTORAGE == null ? true : (bool)currrole.LimitBySTORAGE;
|
|
|
|
|
|
_userInfo.LimitByUser = currrole.LimitByUser == null ? true : (bool)currrole.LimitByUser;
|
|
|
|
|
|
//如果 _userInfo.LimitBySTORAGE == true
|
|
|
//从VW_OP_WMS_STOREHOUSE_USERLIMIT中查出这个用户userid的所有记录
|
|
|
//据此查出所有他可以看的仓库id 然后转换为四位编码
|
|
|
if (_userInfo.LimitBySTORAGE) {
|
|
|
var userStorehouseLimitList = DBServerProvider.DbContext.Set<OP_WMS_STOREHOUSE_USERLIMIT>().Where(x => x.USERID == _userInfo.User_Id).Select(s=>s.Pid).ToList();
|
|
|
var storehouseList = DBServerProvider.DbContext.Set<OP_WMS_STOREHOUSE>().Where(x => userStorehouseLimitList.Contains( x.Id )).ToList();
|
|
|
_userInfo.STOREHOUSEList = new List<string>();
|
|
|
foreach (var item in storehouseList) {
|
|
|
_userInfo.STOREHOUSEList.Add(item.AREACODE);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (_userInfo != null && !_userInfo.User_Id.isNullorEmpty())
|
|
|
{
|
|
|
CacheService.AddObject(key, _userInfo);
|
|
|
}
|
|
|
return _userInfo ?? new UserInfo();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取角色权限时通过安全字典锁定的角色id
|
|
|
/// </summary>
|
|
|
private static ConcurrentDictionary<string, object> objKeyValue = new ConcurrentDictionary<string, object>();
|
|
|
|
|
|
/// <summary>
|
|
|
/// 角色权限的版本号
|
|
|
/// </summary>
|
|
|
private static readonly Dictionary<string, string> rolePermissionsVersion = new Dictionary<string, string>();
|
|
|
|
|
|
/// <summary>
|
|
|
/// 每个角色ID对应的菜单权限(已做静态化处理)
|
|
|
/// 每次获取权限时用当前服务器的版本号与redis/memory缓存的版本比较,如果不同会重新刷新缓存
|
|
|
/// </summary>
|
|
|
private static readonly Dictionary<string, List<Permissions>> rolePermissions = new Dictionary<string, List<Permissions>>();
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取用户所有的菜单权限
|
|
|
/// </summary>
|
|
|
|
|
|
public List<Permissions> Permissions
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return GetPermissionsByRoleId(RoleId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取单个表的权限
|
|
|
/// </summary>
|
|
|
/// <param name="tableName"></param>
|
|
|
/// <returns></returns>
|
|
|
public Permissions GetPermissions(string tableName)
|
|
|
{
|
|
|
return GetPermissionsByRoleId(RoleId).Where(x => x.TableName == tableName).FirstOrDefault();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 自定条件查询权限
|
|
|
/// </summary>
|
|
|
/// <param name="func"></param>
|
|
|
/// <returns></returns>
|
|
|
public Permissions GetPermissions(Func<Permissions, bool> func)
|
|
|
{
|
|
|
return GetPermissionsByRoleId(RoleId).Where(func).FirstOrDefault();
|
|
|
}
|
|
|
|
|
|
private List<Permissions> ActionToArray(List<Permissions> 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<Permissions> MenuActionToArray(List<Permissions> permissions)
|
|
|
{
|
|
|
permissions.ForEach(x =>
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth)
|
|
|
? new string[0]
|
|
|
: x.UserAuth.DeserializeObject<List<Sys_Actions>>().Select(s => s.Value).ToArray();
|
|
|
}
|
|
|
catch { }
|
|
|
finally
|
|
|
{
|
|
|
if (x.UserAuthArr == null)
|
|
|
{
|
|
|
x.UserAuthArr = new string[0];
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
return permissions;
|
|
|
}
|
|
|
public List<Permissions> GetPermissionsByRoleId(string roleId)
|
|
|
{
|
|
|
if (IsRoleIdSuperAdmin(roleId))
|
|
|
{
|
|
|
var permissions_I = DBServerProvider.DbContext.Set<Sys_Menu>().Where(x => x.Enable == 1).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,
|
|
|
});
|
|
|
|
|
|
var permissions= permissions_I.ToList();
|
|
|
|
|
|
//var menutablename = new List<string>();
|
|
|
//foreach (var item in permissions) {
|
|
|
// menutablename.Add(item.TableName);
|
|
|
//}
|
|
|
|
|
|
//var alltable = DBServerProvider.DbContext.Set<Sys_TableInfo>().Where(x => !menutablename.Contains(x.TableName)).ToList();
|
|
|
|
|
|
|
|
|
//foreach (var item in alltable) {
|
|
|
// permissions.Add(new Permissions { Menu_Id = 9999, ParentId=9999,TableName= item.TableName.ToLower(), })
|
|
|
//}
|
|
|
|
|
|
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<Permissions>();
|
|
|
}
|
|
|
|
|
|
//锁定每个角色,通过安全字典减少锁粒度,否则多个同时角色获取缓存会导致阻塞
|
|
|
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<Permissions>();
|
|
|
}
|
|
|
|
|
|
//没有redis/memory缓存角色的版本号或与当前服务器的角色版本号不同时,刷新缓存
|
|
|
var dbContext = DBServerProvider.DbContext;
|
|
|
List<Permissions> _permissions = (from a in dbContext.Set<Sys_Menu>()
|
|
|
join b in dbContext.Set<Sys_RoleAuth>()
|
|
|
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 ?? ""
|
|
|
}).ToList();
|
|
|
|
|
|
var menutablename = new List<string>();
|
|
|
foreach (var item in _permissions)
|
|
|
{
|
|
|
menutablename.Add(item.TableName);
|
|
|
}
|
|
|
|
|
|
var alltable = DBServerProvider.DbContext.Set<Sys_TableInfo>().Where(x => !menutablename.Contains(x.TableName)).ToList();
|
|
|
|
|
|
|
|
|
foreach (var item in alltable)
|
|
|
{
|
|
|
_permissions.Add(new Permissions { Menu_Id = 9999, ParentId = 9999, TableName = item.TableName.ToLower(),UserAuth= "Search,Add,Delete,Update,Import,Export,Upload,Audit" });
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 判断是否有权限
|
|
|
/// </summary>
|
|
|
/// <param name="tableName"></param>
|
|
|
/// <param name="authName"></param>
|
|
|
/// <param name="roleId"></param>
|
|
|
/// <returns></returns>
|
|
|
public bool ExistsPermissions(string tableName, string authName, string roleId = "")
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace( roleId)) roleId = RoleId;
|
|
|
tableName = tableName.ToLower();
|
|
|
authName = authName.ToLower();
|
|
|
return GetPermissionsByRoleId(roleId).Any(x => x.TableName == tableName && x.UserAuthArr.Contains(authName));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 判断是否有权限
|
|
|
/// </summary>
|
|
|
/// <param name="tableName"></param>
|
|
|
/// <param name="authName"></param>
|
|
|
/// <param name="roleId"></param>
|
|
|
/// <returns></returns>
|
|
|
public bool ExistsPermissions(string tableName, ActionPermissionOptions actionPermission, string roleId ="")
|
|
|
{
|
|
|
return ExistsPermissions(tableName, actionPermission.ToString(),roleId);
|
|
|
}
|
|
|
public Guid UserId
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
Guid result = Guid.Empty;
|
|
|
try
|
|
|
{
|
|
|
//var _r=(Context.User.FindFirstValue(JwtRegisteredClaimNames.Jti)
|
|
|
//?? Context.User.FindFirstValue(ClaimTypes.NameIdentifier)).GetInt();
|
|
|
var r1 = Context.User.FindFirstValue(JwtRegisteredClaimNames.Jti);
|
|
|
var r2 = Context.User.FindFirstValue(ClaimTypes.NameIdentifier);
|
|
|
if (r1 == null && r2 == null) result = Guid.Empty;
|
|
|
else
|
|
|
{
|
|
|
var _r = (r1 ?? r2).ToString();
|
|
|
result = new Guid(_r);
|
|
|
}
|
|
|
|
|
|
|
|
|
//result = (Context.User.FindFirstValue(JwtRegisteredClaimNames.Jti)
|
|
|
//?? Context.User.FindFirstValue(ClaimTypes.NameIdentifier)).ToString();
|
|
|
return result;
|
|
|
}
|
|
|
catch (Exception e) {
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public string UserName
|
|
|
{
|
|
|
get { return UserInfo.UserName; }
|
|
|
}
|
|
|
|
|
|
public string UserTrueName
|
|
|
{
|
|
|
get { return UserInfo.UserTrueName; }
|
|
|
}
|
|
|
|
|
|
public string Token
|
|
|
{
|
|
|
get { return UserInfo.Token; }
|
|
|
}
|
|
|
|
|
|
public string RoleId
|
|
|
{
|
|
|
get { return UserInfo.Role_Id; }
|
|
|
}
|
|
|
|
|
|
public void LogOut(Guid userId)
|
|
|
{
|
|
|
CacheService.Remove(userId.GetUserIdKey());
|
|
|
}
|
|
|
|
|
|
public bool HaveLogin(Guid userId)
|
|
|
{
|
|
|
var uid = userId.GetUserIdKey();
|
|
|
var _r = CacheService.Get<UserInfo>(uid);
|
|
|
if (_r != null)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
else{
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|