基于基于角色的安全性隐藏 Html.ActionLinks
我在 _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>
}
而且效果很好,对非编辑者隐藏了“创建”链接,但我对以这种方式处理它是否好持观望态度,而且我可以看到,我遇到了规则发生变化的情况,然后我有两个位置需要保持同步:控制器操作上的属性和视图中的代码。
这是一个合理的做法吗?有更好的方法来解决这个问题吗?
I use @RenderSection("Contextual", false)
within my _Layout.cshtml to allow different views to render their particular content there. Some don't have any, others do.
Additionally, I use role-based security and an ActionFilter to control whether a particular user has access to particular controller actions and thus routes on my site.
What I'd like to do is provide a @RenderSection("Contextual", false)
section on my _Layout.cshtml and then have the particular page provide whatever contextual stuff makes sense for that page and have the corresponding controller handle the vetting of whether a user can perform an action and maybe even see that the options exist but I'm not sure that I'm thinking about this correctly. Here's how things are currently:
Right now I've got a section in one of my Index.cshtml files like so:
@section Contextual {
<div>@Html.ActionLink("Create New", "Create")</div>
<div>@Html.ActionLink("Generate Report", "Report")</div>
<div>@Html.ActionLink("Other Stuff", "Other")</div>
}
and then in my corresponding controller, I've got something like so:
[Authorize(Roles = "Editor")]
public ActionResult Create()
{
// stuff
}
This will work as I want (non-Editors won't get to create new items) but the Create entry is there for all to see. I can do something like so:
@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>
}
And that works well enough, hiding the Create link from the non-Editors, but I'm on the fence about whether it's good or not to handle it this way plus I can see that down the road I've got the situation where the rules change and then I've got two locations to keep in sync: the attribute on the controller action and the code in the view.
Is this a reasonable approach? Is there a better way to approach this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我非常喜欢@TJB 的回答,并且认为我实际上会做类似的事情。但如果您想走不同的路线...您可以创建自己的 LinkExtensions 来超载标准 LinkExtensions。
这里假设“YourAccessStuff”实际上已实现。这将集中这些访问检查,而不是将它们粘贴在每个 ActionLink 上。明显的缺点是您仍然可能忘记进行安全检查。使用某种依赖注入也会让这变得更好。
I like @TJB's answer a lot, and think I'll actually do something similiar. But if you want to go a different route... you could create your own LinkExtensions that overload the standard LinkExtensions.
Assume here that "YourAccessStuff" is actually implemented. This would centralize those access checks as opposed to sticking them on every ActionLink. The downside obviously is that you can still forget to put your security check on. Using some sort of dependency injection would also make this nicer.
我喜欢使用对于控制器上填充的视图模型更明确的标志。
例如:
因此,您需要将此标志添加到您的视图模型中,或者可能添加到你的视图模型。您可以创建自定义操作筛选器,以跨多个控制器填充它或执行一些操作在您的控制器基类中进行处理。
我还想定义一个方便的扩展方法:
根据您使用的 API,您可能还需要扩展
MvcHtmlString
。然后在视图中:
您可以决定对
div
执行什么操作,您可能想要另一个将链接包装在 div 中的助手,或者您可以使用 CSS 来实现您想要的任何视觉布局我们要去。I like to use flags that are more explicit for the view model that are populated on the contorller.
For example:
So, you would need to add this flag to your view model or possibly in the base class of your view models. You could go the route of creating a Custom Action Filter to populate it across several controllers or do some handling in your controller base class.
I also like to define a handy extension method:
Depending on which APIs you're using, you may also need to extend
MvcHtmlString
.Then in the view:
You can decide what you would like to do about the
div
, you may want to have another helper that wraps links in divs, or maybe you can use CSS to achieve whatever visual layout you're going for.