根据Role确定用户是否有权访问给定的Controller Action
本文关键字:访问 Controller Action Role 用户 是否 根据 | 更新日期: 2023-09-27 17:54:07
我正试图为我的ASP.NET MVC4 web application
建立一个动态菜单。当我构造菜单时,我想确保用户不应该访问的菜单项不会显示在菜单中。
我使用表单身份验证和[Authorize]
属性,每个页面都需要一个给定的角色。
给定两个字符串(Controller and Action)
,和一个登录的用户,我怎么能确定如果用户将有访问控制器动作?
我所有的菜单数据都存储在数据库中。我呈现菜单的计划是构造一个菜单数据的JSON对象,并将其嵌入到视图中。然后在客户端,我将使用Handlebars.js
并将菜单JSON object
插入到模板中。
我要做的是检查权限在给定的控制器/操作的用户,因为我正在渲染菜单数据。我最初的想法是使用反射并查找控制器动作方法,检查是否存在授权属性,并检查当前登录的用户是否具有必要的角色访问该页面。如果没有,则不会呈现菜单项。
我总是不愿意使用reflection
,然而,通常倾向于有一个更容易的方法来做事情。
public static IEnumerable<MethodInfo> GetActions(string controller, string action)
{
return Assembly.GetExecutingAssembly().GetTypes()
.Where(t =>(t.Name == controller && typeof(Controller).IsAssignableFrom(t)))
.SelectMany(
type =>
type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(a => a.Name == action && a.ReturnType == typeof(ActionResult))
);
}
然后var roles = ((AuthorizeAttribute) (GetActions("ControllerName" + "Controller", "ActionName").First().GetCustomAttributes(typeof (AuthorizeAttribute), false)[0])).Roles;
if(roles.Contains("admin or smth"))
{
doSomsing();
}
我实现了一个非常类似的场景。唯一的区别是我的菜单存储在XML文件中。
既然你有你的菜单数据存储在数据库中,我建议你添加一个包含安全信息的xml字段到每个菜单记录;或者,创建一个将菜单项映射到用户的新表。表可以是这样的:
MenuItemName (id) User
---------------------------------------
ViewVacationHistory (12) firstuser
ViewVacationHistory (12) seconduser
ApproveVacationRequest (10) seconduser
现在,当你的控制器接收到将导致显示菜单项的请求时,因为你的控制器是用Authorize属性装饰的,它将在HttpContext中接收用户。这里您只需在数据库中查询匹配的菜单项,然后相应地呈现菜单。
使用ActionFilter Attribute根据Role对用户进行过滤http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-custom-action-filters
创建名为Rolevalidation的类并添加如下代码
public class AuthorizeRoles : AuthorizeAttribute
{
List<string> roles = new List<string>(“your list of roles”);
bool isAuthenticated = false;
for (int i = 0; i < roles.Count(); i++)
{
if (u.Role.Name == roles[i])
{
isAuthenticated = true;
break;
}
}
if (isAuthenticated)
{
SetCachePolicy(filterContext);
}
else
{
filterContext.Result = new RedirectResult("~/Error");
}
}
将此代码添加到每个控制器的开头* [AuthorizeRoles(Roles = "SuperAdmin")]
假设您有一个包含所有菜单html代码的视图,可能使用:
会更好<ul class="menu">
<li>
@Html.ActionLink("Home", "Index", "Home")
</li>
@if (System.Web.Security.Roles.IsUserInRole(User.Identity.Name, "Administrator"))
{
<li>
@Html.ActionLink("Statistics", "Index", "Stats")
</li>
}
</ul>
希望这对你有帮助!
链接将由来自动作和控制器的json对象生成。
json对象应该有一个链接列表(或实现菜单项所需的任何内容),该列表应该通过存储在数据库中的排序设置生成,告诉每个用户要显示哪些链接。
除此之外如果用户有URL呢在这种情况下你需要使用
https://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.users (v = vs.118) . aspx
您可以使用Authorize属性来装饰控制器[Authorize(AuthorizationContext)]
中的操作,或者您可以扩展Authorize属性以进行自定义授权;
您还可以在字典中定义一些约定,其中定义控制器的Create操作需要一个Create类型授权。
Dictionary<string, Right> actionConventions = new Dictionary<string, Right>
{
{ "Index", Right.View },
{ "List", Right.View },
{ "Open", Right.View },
{ "Create", Right.Create},
{ "Edit", Right.Edit },
{ "Delete", Right.Delete }
}
和覆盖AuthorizeAttribute
的OnAuthorization
和Authorize
方法,如果操作坚持字典中定义的约定,则检查约定,或者检查特定的条件,其中Authorize(AuthorizationContext)
用于操作或HandleUnauthorizedRequest(AuthorizationContext)
。
处理菜单,您可以创建一个授权服务,在该服务中返回当前用户的权限,并添加一个包含用户权限的类,并且在呈现模型时检查Model,是否应该呈现菜单项。
授权属性MSDN