我正在尝试为ASP.NET MVC4 web application
构建动态菜单。当我构建菜单时,我想确保用户不应该访问的菜单项不会显示在菜单中。
我正在使用表单身份验证和[Authorize]
属性,每个页面都需要一个角色。
给定两个字符串(Controller and Action)
和一个登录用户,如何确定用户是否有权访问该控制器操作?
我的所有菜单数据都存储在数据库中。我渲染菜单的计划是构造菜单数据的JSON对象并将其嵌入到View中。然后客户端我将使用Handlebars.js
并将菜单JSON object
插入模板。
我要做的是在渲染菜单数据时检查用户对给定Controller / Action的权限。我最初的想法是使用反射并查找控制器操作方法并检查是否存在Authorize属性,并检查当前登录用户是否具有访问该页面的必要角色。如果没有,则不会呈现菜单项。
我总是不愿意使用reflection
但是,通常会有一种更简单的做事方式。
答案 0 :(得分:1)
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();
}
答案 1 :(得分:0)
我实施了一个非常类似的场景。 唯一的区别是我的菜单存储在XML文件中。
由于您将菜单数据存储在数据库中,我建议您为每个菜单记录添加一个包含安全信息的xml字段;或者,有一个新的表将菜单项映射到用户。 该表可能如下所示:
MenuItemName (id) User
---------------------------------------
ViewVacationHistory (12) firstuser
ViewVacationHistory (12) seconduser
ApproveVacationRequest (10) seconduser
现在,当您的控制器收到导致显示菜单项的请求时,并且由于您的控制器使用Authorize属性进行修饰,它将在HttpContext中接收用户。在这里,您只需在数据库中查询匹配的菜单项,然后相应地渲染菜单。
答案 2 :(得分:0)
使用ActionFilter属性根据角色过滤用户 http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-custom-action-filters
答案 3 :(得分:0)
创建名为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”)]
答案 4 :(得分:0)
链接将由来自动作和控制器的json对象生成。
json对象应该有一个链接列表(或实现菜单项所需的内容),该列表应该通过存储在数据库中的各种设置生成,告诉每个用户要显示的链接。
除此之外,如果用户有URL,那么在这种情况下你需要使用
https://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.users(v=vs.118).aspx
答案 5 :(得分:0)
假设您有一个包含所有菜单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>
希望这有帮助!
答案 6 :(得分:-1)
您可以使用Authorize属性来装饰来自控制器[Authorize(AuthorizationContext)]
的操作,或者您可以扩展authorize属性以进行自定义授权;
您还可以在字典中定义一些约定,您可以在其中定义控制器的“创建”操作需要创建类型授权a.s.o.
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 }
}
并覆盖OnAuthorization
的{{1}}和Authorize
方法,如果操作符合字典中定义的约定或检查您{{1}的特定条件,请检查约定行动或AuthorizeAttribute
。
处理菜单可以创建授权服务,在该服务中返回当前用户的权限并添加包含用户权限的类,并在渲染模型时检查模型,是否应呈现菜单项或不