微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

安全修剪菜单作为部分视图 Menu.cshtml MenuController.cs _UsersAndRolesPartial.cshtml

如何解决安全修剪菜单作为部分视图 Menu.cshtml MenuController.cs _UsersAndRolesPartial.cshtml

我正在_Layout.cshtml文件中呈现一个菜单。仅当用户管理员角色时,菜单的一部分才应呈现。我们在数据库中使用自定义角色。管理员字段以单个字符“ Y”或“ N”返回。它最初是一个旧版应用程序,正在迁移到MVC5。不使用LINQ或Entity Framework。

我正在将菜单创建为Menu.cshtml的部分视图:

<ul class="nav" ui-nav>
    ...

    @if ((bool)ViewData["Admin"] == true)  
    {
         <li>
             <a href="#"><span>Users and Roles</span></a>
         </li>
    }
</ul>

我的_Layout.cshtml文件

...
    <aside id="aside" class="ui-aside">
        @Html.Action("Menu")
    </aside>
...

问题出在控制器的操作方法上。我的意图是返回一个布尔值,然后根据部分视图中的值简单地切换菜单受保护部分的呈现。现在,它在应该显示菜单的浏览器中呈现True或False,因为该布尔值是从action方法中作为HTML字符串返回的。

我知道我可以从动作方法中以字符串形式返回菜单的那一部分,但是我想避免这种情况,因为菜单中的其他部分将根据角色值进行渲染。我不想以大量的局部视图结束。如果可能的话,我也想避免使用标签助手。我只是想根据action方法中的布尔值来切换部分视图中HTML菜单部分的呈现。

操作方法

[ChildActionOnly]
public bool Menu()
{
    using (connection...)
    {
        ...
        object adminObject = command.ExecuteScalar();
        if (adminObject != null)
        {
            string admin = adminObject.ToString();
            if (admin == "Y")
                ViewData["Admin"] = true;
            else
                ViewData["Admin"] = false;
        }
    }
    return (bool)ViewData["Admin"];
}

解决方法

您知道Html.Action返回MvcHtmlString,这就是为什么它显示TrueFalse

您乐于尝试这样的事情吗?

_Layout.cshtml

 <li>@if(Html.Action("Menu").ToString().ToLower()=="true") { 
    @Html.Partial("_Menu")
}</li>

局部视图

<ul class="nav" ui-nav>
    <li>
        <a href="#"><span>Users and Roles</span></a>
    </li>
</ul>
,

您的局部视图可以声明一个附带的模型。您可以使用@Html.Action()

,而不是使用@Html.RenderAction()将结果作为HTML字符串返回。
  1. 运行您的逻辑以获取当前登录用户的角色状态
  2. 为部分视图构建视图模型
  3. 将部分视图连同视图模型直接返回到响应

通过这种方式,您如何获取用户角色状态的逻辑被“封装”在子操作方法中,而显示或隐藏菜单部分的逻辑被“封装”在局部视图中。 / p>

Menu.cshtml

在菜单中,您希望呈现仅对管理员可用的部分,您可以使用@Html.RenderAction()buildUsersAndRoles控制器中执行menu动作(我刚刚做了):>

<ul class="nav" ui-nav>
    ...
    @Html.RenderAction("buildUsersAndRoles","menu",new { area = "" })
    ...
</ul>

MenuController.cs

基本思想是渲染逻辑以获取所需的必要数据,包括用于显示用户是否为admin的标志。然后,基于这些,您可以确定要在视图模型内部传递的内容。

在这里,我的方法是如果用户不是admin则传递NULL,因为没有可显示的内容,否则传递包含用户和角色信息的视图模型:

public class MenuController : Controller
{
    ...

    [ChildActionOnly]
    public ActionResult BuildUsersAndRoles()
    {
        using (connection...)
        {
            ...
            object adminObject = command.ExecuteScalar();
            if (adminObject != null)
            {
                string admin = adminObject.ToString();
                if (admin == "Y")
                {
                    var vm = new UsersAndRolesViewModel
                    {
                        Users = new List<...>(),Roles = new List<...>(),...
                    };

                    return PartialView("_UsersAndRolesPartial",vm);
                }
            }

            return PartialView("_UsersAndRolesPartial");
        }
    }

    ...
}

_UsersAndRolesPartial.cshtml

最后,在仅当用户具有管理员角色时要显示的部分中,您可以使用视图模型:

@model ...UsersAndRolesViewModel

@if (Model != null)
{
    <h5>Users and Roles</h5>

    ...
}
,

我假设单击菜单链接的操作将涉及使用asp.net授权控制访问权限来获取控制器或页面。

因此,这是我对asp.net核心的看法(它不能回答您的问题,但将来可能会很有趣)。编写标签帮助程序,以删除用户无权查看的标签。这样,您可以重新使用相同的授权策略名称来控制可见性和权限。

    [HtmlTargetElement(Attributes = "policy")]
    public class PolicyTagHelper : TagHelper
    {
        private readonly IAuthorizationService authService;
        private readonly IHttpContextAccessor httpContextAccessor;

        public PolicyTagHelper(IAuthorizationService authService,IHttpContextAccessor httpContextAccessor)
        {
            this.authService = authService;
            this.httpContextAccessor = httpContextAccessor;
        }

        public string Policy { get; set; }

        public override async Task ProcessAsync(TagHelperContext context,TagHelperOutput output)
        {
            if (!(await authService.AuthorizeAsync(httpContextAccessor.HttpContext.User,Policy)).Succeeded)
                output.SuppressOutput();
        }
    }

用法;

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages(options => {
                options.Conventions
                    .AuthorizePage("/UserRole","Admin");
            }
            services.AddAuthorization(options =>
            {
                options.AddPolicy("Admin",policy => ...);
            }
        }

<ul class="nav" ui-nav>
     <li policy="Admin">
         <a href="#"><span>Users and Roles</span></a>
     </li>
</ul>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。