【问题标题】:Hiding Html.ActionLinks based on Role-based security基于基于角色的安全性隐藏 Html.ActionLinks
【发布时间】:2011-08-19 14:37:18
【问题描述】:

我在我的_Layout.cshtml 中使用@RenderSection("Contextual", false) 来允许不同的视图在那里呈现它们的特定内容。有些没有,有些有。

此外,我使用基于角色的安全性和 ActionFilter 来控制特定用户是否有权访问特定控制器操作并因此在我的站点上路由。

我想做的是在我的 _Layout.cshtml 上提供一个@RenderSection("Contextual", false) 部分,然后让特定页面提供对该页面有意义的任何上下文内容并且具有相应的控制器句柄审查用户是否可以执行操作甚至可能看到选项存在,但我不确定我是否正确地考虑了这一点。以下是目前的情况:

现在我的 Index.cshtml 文件中有一个部分,如下所示:

@section Contextual {
  <div>@Html.ActionLink("Create New", "Create")</div>
  <div>@Html.ActionLink("Generate Report", "Report")</div>
  <div>@Html.ActionLink("Other Stuff", "Other")</div>
}

然后在我相应的控制器中,我有这样的东西:

[Authorize(Roles = "Editor")]
public ActionResult Create()
{
   // stuff
}

这将按我的意愿工作(非编辑者无法创建新项目),但创建条目可供所有人查看。我可以这样做:

@section Contextual {
  @if (User.IsInRole("Editor"))
  {
     <div>@Html.ActionLink("Create New", "Create")</div>
  }
  <div>@Html.ActionLink("Generate Report", "Report")</div>
  <div>@Html.ActionLink("Other Stuff", "Other")</div>
}

而且效果很好,对非编辑者隐藏了“创建”链接,但我对这样处理它是否合适持怀疑态度,而且我可以看到在路上我已经得到了规则更改的情况,然后我有两个位置要保持同步:控制器操作上的属性和视图中的代码。

这是一个合理的方法吗?有没有更好的方法来解决这个问题?

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-3 roles


    【解决方案1】:

    我喜欢为控制器上填充的视图模型使用更明确的标志。

    例如:

     // on the controller
     viewModel.CanCrete = User.IsInRole("Editor");
     // ...snip...
     return View(viewModel);
    }
    

    因此,您需要将此标志添加到您的视图模型或可能在您的视图模型的基类中。你可以创建一个Custom Action Filter 来在多个控制器中填充它,或者在你的控制器基类中做一些处理。

    我也喜欢定义一个方便的扩展方法:

    public static string If( this string s, bool condition )
    {
      return condition ? s : String.Empty;
    }
    

    根据您使用的 API,您可能还需要扩展 MvcHtmlString

    然后在视图中:

    @section Contextual {
      <div>@Html.ActionLink("Create New", "Create").If(Model.CanCrete)</div>
      <div>@Html.ActionLink("Generate Report", "Report")</div>
      <div>@Html.ActionLink("Other Stuff", "Other")</div>
    }
    

    你可以决定你想对div做什么,你可能想要另一个在 div 中包装链接的助手,或者你可以使用 CSS 来实现你想要的任何视觉布局。

    【讨论】:

    • 感谢您的回复。我想我喜欢你的解决方案的想法是用户角色检查在控制器中完成,然后视图真的不会担心为什么启用创建功能/disabled - 将该信息分开。允许使用控制器端的任意数量的原因来翻转 CanCreate 位。好东西。我绝对喜欢那个扩展方法——它方便的。 :)
    • @itsmatt 没问题。我正在处理的当前系统充满了基于(上下文+角色)的安全性,因此经常遇到这种情况。我认为您达到了关键点,将视图的关注点与控制器分开。另一种方法可能是根据角色生成链接列表(也可以在控制器中填充)
    【解决方案2】:

    我非常喜欢@TJB 的回答,并认为我实际上会做类似的事情。但是,如果您想走不同的路线……您可以创建自己的 LinkExtensions 来重载标准 LinkExtensions。

    public static class MyLinkExtensions
    {
        public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, YourAccessStuff access)
        {
            if(access.Has(actionName))
            {
                ActionLink(htmlHelper, linkText, actionName);            
            }
            else
            {
                // Maybe only show the link text as if it's disabled and not a link?
                // Maybe do nothing?          
            }
        }
    }
    

    这里假设实际实现了“YourAccessStuff”。这将集中这些访问检查,而不是将它们粘贴在每个 ActionLink 上。缺点显然是您仍然可能忘记进行安全检查。使用某种依赖注入也会使这更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-21
      • 2011-05-12
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多