【问题标题】:Determine if a user will have access to a given Controller Action based on Role根据角色确定用户是否有权访问给定的控制器操作
【发布时间】:2013-01-17 15:22:12
【问题描述】:

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

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

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


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


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

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

【问题讨论】:

  • 如何渲染菜单?它是视图的一部分,还是您有某种子视图,例如 RenderControl 或 RenderAction 方法?此外,您似乎在问两个问题。您想基于安全性隐藏/显示菜单项,还是您已经弄清楚了那部分?
  • 对于隐藏/显示菜单项,这里可能有一些帮助:stackoverflow.com/questions/8411224/…
  • 您必须建立您的声明并检查用户是否拥有声明。实现安全性的最佳方式不是基于角色(不过对菜单很有用),而是基于操作的安全性。
  • 可以使用 MvcSiteMapProvider 生成菜单。

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


【解决方案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();
}

【讨论】:

  • 这个解决方案只考虑了动作上的AuthorizeAttribute,而不考虑控制器上定义的AuthorizeAttribute
【解决方案2】:

我已经实现了一个非常相似的场景。 唯一的区别是我的菜单存储在 XML 文件中。

由于您将菜单数据存储在数据库中,我建议您在每个菜单记录中添加一个包含安全信息的 xml 字段;或者,有一个将菜单项映射到用户的新表。 该表可能如下所示:

MenuItemName (id)             User
---------------------------------------
ViewVacationHistory (12)      firstuser
ViewVacationHistory (12)      seconduser
ApproveVacationRequest (10)   seconduser

现在,当您的控制器接收到将导致显示菜单项的请求时,并且由于您的控制器已使用 Authorize 属性进行修饰,它将在 HttpContext 中接收用户。在这里,您只需在数据库中查询匹配的菜单项,然后相应地呈现菜单。

【讨论】:

    【解决方案3】:

    【讨论】:

      【解决方案4】:

      创建名为 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")]

      【讨论】:

      • 希望对您有所帮助。
      【解决方案5】:

      假设您有一个包含所有菜单 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】:

        链接将由来自动作和控制器的 json 对象生成。

        json 对象应该有一个链接列表(或实现菜单项所需的内容),该列表应该由存储在数据库中的各种设置生成,告诉每个用户要显示哪些链接。

        除此之外,如果用户有 URL,那么在这种情况下你需要使用

        https://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.users(v=vs.118).aspx

        【讨论】:

          【解决方案7】:

          您可以使用 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 }
          }
          

          并覆盖AuthorizeAttributeOnAuthorizationAuthorize 方法,如果操作符合字典中定义的约定,则检查约定,或者检查特定条件,您可以使用Authorize(AuthorizationContext) 执行操作或@987654328 @。

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

          Authorize Attribute MSDN

          【讨论】:

            猜你喜欢
            • 2014-11-30
            • 1970-01-01
            • 2014-08-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-26
            • 1970-01-01
            • 2018-07-27
            相关资源
            最近更新 更多