确定用户是否可以基于角色访问给定的Controller Action

时间:2013-01-17 15:22:12

标签: c# asp.net asp.net-mvc-4 asp.net-membership

我正在尝试为ASP.NET MVC4 web application构建动态菜单。当我构建菜单时,我想确保用户不应该访问的菜单项不会显示在菜单中。

我正在使用表单身份验证和[Authorize]属性,每个页面都需要一个角色。

给定两个字符串(Controller and Action)和一个登录用户,如何确定用户是否有权访问该控制器操作?


我的所有菜单数据都存储在数据库中。我渲染菜单的计划是构造菜单数据的JSON对象并将其嵌入到View中。然后客户端我将使用Handlebars.js并将菜单JSON object插入模板。


我要做的是在渲染菜单数据时检查用户对给定Controller / Action的权限。我最初的想法是使用反射并查找控制器操作方法并检查是否存在Authorize属性,并检查当前登录用户是否具有访问该页面的必要角色。如果没有,则不会呈现菜单项。

我总是不愿意使用reflection但是,通常会有一种更简单的做事方式。

7 个答案:

答案 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)

答案 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

处理菜单可以创建授权服务,在该服务中返回当前用户的权限并添加包含用户权限的类,并在渲染模型时检查模型,是否应呈现菜单项或不

Authorize Attribute MSDN