根据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,然而,通常倾向于有一个更容易的方法来做事情。

根据Role确定用户是否有权访问给定的Controller Action

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 }
}

和覆盖AuthorizeAttributeOnAuthorizationAuthorize方法,如果操作坚持字典中定义的约定,则检查约定,或者检查特定的条件,其中Authorize(AuthorizationContext)用于操作或HandleUnauthorizedRequest(AuthorizationContext)

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

授权属性MSDN