c# - 获取 AspNet 用户 RoleId 以进行权限比较
问题描述
我有一个区域,其中 RoleId 作为字符串保存在权限表中。我正在对 Id 进行比较以提取角色的所有权限。我正在像这样获取当前登录的用户 RoleId。
var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
string roleid = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);
它不喜欢使用字符串。我正进入(状态
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string'
这是我进行比较的地方,注意权限可以有 UserId 或 RoleId,我没有这个设置的 UserId 问题。
var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));
是否有不同的方法来获取 RoleId 或不同的措辞来进行比较?
谢谢
更新:在下面添加了控制器。抱歉,时间长了。。
protected override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
try
{
//int roleid = int.Parse(Env.GetUserInfo("roleid"));
//int userid = int.Parse(Env.GetUserInfo("userid"));
string userid = User.Identity.GetUserId();
//string userid = Env.GetUserInfo("userid");
//string roleid = Env.GetUserInfo("roleid");
var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
// Select will return collection as opposed to scalar/single value. Pay attention to datatype here.
IEnumerable<string> currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);
//string roleid = roles;
var descriptor = context.ActionDescriptor;
var actionName = descriptor.ActionName.ToLower();
var controllerName = descriptor.ControllerDescriptor.ControllerName.ToLower();
var controller = descriptor.ControllerDescriptor.ControllerName;
var GetOrPost = context.HttpContext.Request.HttpMethod.ToString();
var checkAreaName = context.HttpContext.Request.RequestContext.RouteData.DataTokens["area"];
string AreaName = "";
if (checkAreaName != null)
{
AreaName = checkAreaName.ToString().ToLower() + "/";
}
var cacheItemKey = "AllMenuBar";
var global = HttpRuntime.Cache.Get(cacheItemKey);
if (GetOrPost == "POST")
{
// Added index to string 02/03/2020
// Added add to actonName settings 02/08/2020
///if menupermission create,edit,delete then update value "true" in IsMenuChange file
if (controllerName == "menupermission" && (actionName == "add" || actionName == "index" || actionName == "create" || actionName == "edit" || actionName == "delete" || actionName == "multiviewindex"))
{
global = MenuBarCache(cacheItemKey, global, "shortcache");
}
}
if (global == null)//if cashe is null
{
global = MenuBarCache(cacheItemKey, global, "60mincache");//make cache from db
}
var menuaccess = (MenuOfRole[])global;
if (GetOrPost == "GET")
{
if (actionName == "add" || actionName == "index" || actionName == "create" || actionName == "edit" || actionName == "delete" || actionName == "multiviewindex")
{
// Old Impementation May be removed at Cleanup if not used - 02/10/2020
//ViewBag.Add = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsAdd));
//ViewBag.Read = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsRead));
//ViewBag.Create = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsCreate));
//ViewBag.Edit = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsUpdate));
//ViewBag.Delete = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsDelete))();
// Stack Overflow corrections - 02/10/2020
ViewBag.Add = menuaccess.Any(i => i.MenuURL == controllerName && i.IsAdd);
ViewBag.Read = menuaccess.Any(i => i.MenuURL == controllerName && i.IsRead);
ViewBag.Create = menuaccess.Any(i => i.MenuURL == controllerName && i.IsCreate);
ViewBag.Edit = menuaccess.Any(i => i.MenuURL == controllerName && i.IsUpdate);
ViewBag.Delete = menuaccess.Any(i => i.MenuURL == controllerName && i.IsDelete);
ViewBag.Visable = menuaccess.Any(i => i.MenuURL == controllerName && i.IsVisable);
}
}
string menuUrl = AreaName + controllerName + "/" + actionName;
if (IsActionNameEqualToCrudPageName(actionName))
{
menuUrl = AreaName + controllerName;
}
var checkUrl = menuaccess.FirstOrDefault(i => (i.MenuURL == AreaName + controllerName + "/" + actionName) || i.MenuURL == menuUrl);
///checkUrl: check if menu url Exists in MenuPermission if not exists then will be run
if (checkUrl != null)
{
// Changed below line to use string instead of int.. 01/26/2020
//var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));
// Added change to use roles as collection.
var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == userid);
///check menu && roleid && userid
if (checkControllerActionRoleUserId != null)
{
if (IsActionNameEqualToCrudPageName(actionName))
{
CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
}
else
{
if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}
else
{
var checkControllerActionRole = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == null);
if (checkControllerActionRole != null)
{
if (IsActionNameEqualToCrudPageName(actionName))
{
CheckAccessOfPageAction(context, actionName, checkControllerActionRole);
}
else
{
if (checkControllerActionRole.IsRead == false || checkControllerActionRole.IsDelete == false || checkControllerActionRole.IsCreate == false || checkControllerActionRole.IsUpdate == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}
else
{
if (IsThisAjaxRequest() == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}
}
}
catch (Exception)
{ }
}
更新:在执行下面的@Sam 建议后,我还需要找到一种方法,不授予不在权限表中的用户访问权限。避免冗余。如果用户无权访问某些内容,那么我不需要将其添加到权限以确保他们无权访问。如果用户登陆他们无权访问的页面,我添加了以下代码部分以重定向到仪表板。
var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId)
&& (i.UserId == userid || i.UserId == null) || controllerName == "dashboard"// @Sam: This is how we can combine
);
///check menu && roleid && userid
if (checkControllerActionRoleUserId != null)
{
if (IsActionNameEqualToCrudPageName(actionName))
{
CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
}
else
{
if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}
else
{
UnAuthorizedArea(context);
}
解决方案
您的代码中有几个问题。修复当前错误后,您将收到更多错误:
- 您正在将字符串集合分配给字符串(通过字符串 roleid)。目前您收到此错误。修复此错误后,将出现以下错误。
您收到错误的原因是:
以下语句返回登录用户的角色集合(准确地说是角色 ID 集合),而不是单个角色 ID。
string roleid = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);`
然后您尝试在下一条语句中将此角色标识集合分配给标量属性 i.RoleId(通过 i.RoleId = roleid)
var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));`
使用赋值运算符 = 而不是
==
进行比较。因此,您正在尝试将 roleid 分配给 i.RoleId 这是不允许的。使用赋值运算符 = 而不是 == 进行比较。因此,您正在尝试将用户 ID 分配给 i.UserId,这是不允许的。
修复:请修改您的 roleId 部分,如下所示:
var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
// Select will return collection as opposed to scalar/single value. Pay attention to datatype here.
IEnumerable<string> currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);
(或者)
//You can use var in case you do not know the data types of result.
var currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);
currentUserRoles 将包含当前登录用户的所有角色。现在使用该集合,如下所示(请注意条件currentUserRoles.Contains(i.RoleId)。我还修复了 userid 周围的条件。):
var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl
&& currentUserRoles.Contains(i.RoleId) && i.UserId == userid);
或者,可以使用 Where 和 FirstOrDefault 拆分上述语句,如下所示:
// Where statement returns collection of menuaccess items meeting all three conditions
var filteredMenuAccessCollection = menuaccess.Where(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == userid);
// FirstOrDefault will return the first menuaccess item from filteredMenuAccessCollection
var checkControllerActionRoleUserId = filteredMenuAccessCollection.FirstOrDefault();
上面的内容可以进一步改写如下:
var mathingMenuUrlMenuAccessCollection = menuaccess.Where(i => i.MenuURL == menuUrl); // return menuaccess items matching given menuurl
var mathingMenuUrlAndRolesMenuAccessCollection = mathingMenuUrlMenuAccessCollection.Where(i => currentUserRoles.Contains(i.RoleId)); // return menuaccess items matching roles in currentUserRoles
var filteredMenuAccessCollection = mathingMenuUrlAndRolesMenuAccessCollection.Where(i => i.UserId == userid); // return menuaccess items matching given userid
// FirstOrDefault will return the first menuaccess item from filteredMenuAccessCollection
var checkControllerActionRoleUserId = filteredMenuAccessCollection.FirstOrDefault();
总而言之,必须满足所有 3 个条件才能从 menuaccess 集合中获取项目,否则将返回 null。条件评估的顺序是
- 首先它尝试从 menuaccess 集合中找到匹配的 menuUrl 项目。
- 然后尝试查找当前用户角色集合中包含 RoleId 的 menuaccess 项。
- 然后它尝试从 menuaccess 集合中找到匹配的用户 ID 项。
如果有多个 menuaccess 项满足上述 3 个条件,那么它将返回 menuaccess 集合中的第一项,因为我们使用的是 FirstOrDefault。
更新: OnActionExecuting 的简化版本:
protected override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
try
{
//int roleid = int.Parse(Env.GetUserInfo("roleid"));
//int userid = int.Parse(Env.GetUserInfo("userid"));
string userid = User.Identity.GetUserId();
//string userid = Env.GetUserInfo("userid");
//string roleid = Env.GetUserInfo("roleid");
var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
// Select will return collection as opposed to scalar/single value. Pay attention to datatype here.
IEnumerable<string> currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);
//string roleid = roles;
// @Sam: Added this variable
var actionNamesToCompare = new List<string>{"add", "index", "create", "edit", "delete", "multiviewindex"};
var descriptor = context.ActionDescriptor;
var actionName = descriptor.ActionName.ToLower();
var controllerName = descriptor.ControllerDescriptor.ControllerName.ToLower();
var controller = descriptor.ControllerDescriptor.ControllerName;
var GetOrPost = context.HttpContext.Request.HttpMethod.ToString();
var checkAreaName = context.HttpContext.Request.RequestContext.RouteData.DataTokens["area"];
string AreaName = "";
if (checkAreaName != null)
{
AreaName = checkAreaName.ToString().ToLower() + "/";
}
var cacheItemKey = "AllMenuBar";
var global = HttpRuntime.Cache.Get(cacheItemKey);
if (GetOrPost == "POST")
{
// Added index to string 02/03/2020
// Added add to actonName settings 02/08/2020
///if menupermission create,edit,delete then update value "true" in IsMenuChange file
if (controllerName == "menupermission" && actionNamesToCompare.Contains(actionName))
{
global = MenuBarCache(cacheItemKey, global, "shortcache");
}
}
if (global == null)//if cashe is null
{
global = MenuBarCache(cacheItemKey, global, "60mincache");//make cache from db
}
var menuaccess = (MenuOfRole[])global;
if (GetOrPost == "GET")
{
if (actionNamesToCompare.Contains(actionName))
{
// Old Impementation May be removed at Cleanup if not used - 02/10/2020
//ViewBag.Add = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsAdd));
//ViewBag.Read = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsRead));
//ViewBag.Create = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsCreate));
//ViewBag.Edit = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsUpdate));
//ViewBag.Delete = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsDelete))();
// Stack Overflow corrections - 02/10/2020
ViewBag.Add = menuaccess.Any(i => i.MenuURL == controllerName && i.IsAdd);
ViewBag.Read = menuaccess.Any(i => i.MenuURL == controllerName && i.IsRead);
ViewBag.Create = menuaccess.Any(i => i.MenuURL == controllerName && i.IsCreate);
ViewBag.Edit = menuaccess.Any(i => i.MenuURL == controllerName && i.IsUpdate);
ViewBag.Delete = menuaccess.Any(i => i.MenuURL == controllerName && i.IsDelete);
ViewBag.Visable = menuaccess.Any(i => i.MenuURL == controllerName && i.IsVisable);
}
}
// @sam: you can combine menuUrl evaluation like this using ternary operator.
var menuUrl = IsActionNameEqualToCrudPageName(actionName) ? AreaName + controllerName
: AreaName + controllerName + "/" + actionName;
// var checkUrl = menuaccess.FirstOrDefault(i => (i.MenuURL == AreaName + controllerName + "/" + actionName) || i.MenuURL == menuUrl);
// @sam: No need of this if statement
// var checkUrl = menuaccess.FirstOrDefault(i => (i.MenuURL == AreaName + controllerName + "/" + actionName) || i.MenuURL == menuUrl);
///checkUrl: check if menu url Exists in MenuPermission if not exists then will be run
/*if (checkUrl != null)
{
// Changed below line to use string instead of int.. 01/26/2020
//var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));
// Added change to use roles as collection.
// @Sam: Since both if and else are doing same of operations,
// the below if-else can be comibined as follows:
/*var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl &¤tUserRoles.Contains(i.RoleId) && i.UserId == userid);
///check menu && roleid && userid
if (checkControllerActionRoleUserId != null)
{
if (IsActionNameEqualToCrudPageName(actionName))
{
CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
}
else
{
if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}
else
{
var checkControllerActionRole = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == null);
if (checkControllerActionRole != null)
{
if (IsActionNameEqualToCrudPageName(actionName))
{
CheckAccessOfPageAction(context, actionName, checkControllerActionRole);
}
else
{
if (checkControllerActionRole.IsRead == false || checkControllerActionRole.IsDelete == false || checkControllerActionRole.IsCreate == false || checkControllerActionRole.IsUpdate == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}
else
{
if (IsThisAjaxRequest() == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}//
} */
var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl &¤tUserRoles.Contains(i.RoleId)
&& (i.UserId == userid || i.UserId == null) // @Sam: This is how we can combine
);
///check menu && roleid && userid
if (checkControllerActionRoleUserId != null)
{
if (IsActionNameEqualToCrudPageName(actionName))
{
CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
}
else
{
if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
{
UnAuthoRedirect(context);
}
}
}
}
catch (Exception)
{ }
}
您可以针对不同的用户使用您的数据进行测试。
推荐阅读
- python - 使用 time.mktime(datetime.strptime(ti, '%m/%d/%Y %I:%M %p')) 时需要元组或 struct_time 参数错误
- c++ - 如何使用 new 在堆上保存类的字符串变量
- raspberry-pi - 我的树莓派上没有显示 eth0 的静态 IP 地址
- r - data.frame 列作为函数的参数
- angular - HTTP 缓存和 Angular Service Worker
- security - 允许 POST 到谷歌云功能但不允许 GET?
- javascript - 通过脚本从 MS Planner 下载 excel 文件
- python - 将一个数据帧中的匹配值替换为另一个数据帧中的索引值
- java - 是否可以检查线程在 JAVA 中运行在哪个处理器上?
- java - 如何在 Spring Boot 中连接外部数据库,同时保持与主数据库的连接