【问题标题】:MVCSiteMap Node Requring Multiple Roles需要多个角色的 MVCSiteMapNode
【发布时间】:2023-04-01 12:42:02
【问题描述】:

我已经使用 MVCSiteMap 设置了我的菜单,并且我有这个节点:

<mvcSiteMapNode title="Courses Form" controller="Booking" action="Course" roles="CORLIC, VIEWCOBO"/>

我试图强制该节点必须具有角色“CORLIC”和“VIEWCOBO”才能使其可见,但这当然意味着如果用户具有上述任何一种,它将被显示。

这可能吗?

谢谢。

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 roles mvcsitemapprovider


    【解决方案1】:

    角色属性用于与 ASP.NET 的互操作性,不应在仅 MVC 的应用程序中使用。

    对于 MVC,如果您已经在控制器操作上定义了 AuthorizeAttribute,如果启用了 security trimming,MvcSiteMapProvider 将自动选择它们并相应地隐藏匹配的节点。

    [Authorize]
    public ActionResult Course()
    {
        return View();
    }
    
    [Authorize]
    [HttpPost]
    public ActionResult Course(CourseModel model)
    {
        if (ModelState.IsValid)
        {
            // Implementation omitted
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    }
    

    默认的AuthorizeAttribute 接受角色,但它的工作方式与角色属性相同 - 即用户所在的任何角色都会使其成功。

    但是,您可以自己继承 AuthorizeAttribute 并覆盖 IsAuthorized method 以根据需要更改逻辑。

    public class SpecialAuthorizeAttribute : AuthorizeAttribute
    {
        private string _requiredRoles;
        private string[] _requiredRolesSplit = new string[0];
    
        /// <summary>
        /// Gets or sets the required roles. The user must be a member of all roles for it to succeed.
        /// </summary>
        /// <value>
        /// The roles string.
        /// </value>
        /// <remarks>Multiple role names can be specified using the comma character as a separator.</remarks>
        public string RequiredRoles
        {
            get { return _requiredRoles ?? String.Empty; }
            set
            {
                _requiredRoles = value;
                _requiredRolesSplit = SplitString(value);
            }
        }
    
        /// <summary>
        /// Determines whether access for this particular request is authorized. This method uses the user <see cref="IPrincipal"/>
        /// returned via <see cref="HttpRequestContext.Principal"/>. Authorization is denied if the user is not authenticated,
        /// the user is not in the authorized group of <see cref="Users"/> (if defined), or if the user is not in any of the authorized 
        /// <see cref="Roles"/> (if defined).
        /// </summary>
        /// <param name="actionContext">The context.</param>
        /// <returns><c>true</c> if access is authorized; otherwise <c>false</c>.</returns>
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            if (actionContext == null)
            {
                throw new ArgumentNullException("actionContext");
            }
    
            IPrincipal user = actionContext.ControllerContext.RequestContext.Principal;
            if (user == null || user.Identity == null || !user.Identity.IsAuthenticated)
            {
                return false;
            }
    
            // Ensure all of the roles in RequiredRoles are present.
            if (_requiredRolesSplit.Length > 0 && !_requiredRolesSplit.All(user.IsInRole))
            {
                return false;
            }
    
            // Call the base class to check the users and roles there.
            return base.IsAuthorized(actionContext);
        }
    
        /// <summary>
        /// Splits the string on commas and removes any leading/trailing whitespace from each result item.
        /// </summary>
        /// <param name="original">The input string.</param>
        /// <returns>An array of strings parsed from the input <paramref name="original"/> string.</returns>
        internal static string[] SplitString(string original)
        {
            if (String.IsNullOrEmpty(original))
            {
                return new string[0];
            }
    
            var split = from piece in original.Split(',')
                        let trimmed = piece.Trim()
                        where !String.IsNullOrEmpty(trimmed)
                        select trimmed;
            return split.ToArray();
        }
    }
    

    然后您可以使用新属性指定需要哪些角色。

    [SpecialAuthorize(RequiredRoles = "CORLIC, VIEWCOBO")]
    public ActionResult Course()
    {
        return View();
    }
    
    [SpecialAuthorize(RequiredRoles = "CORLIC, VIEWCOBO")]
    [HttpPost]
    public ActionResult Course(CourseModel model)
    {
        if (ModelState.IsValid)
        {
            // Implementation omitted
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    }
    

    另一个可能的选择是将FluentSecurity 用作shown here。为了让 FluentSecurity v2.0 与 MvcSiteMapProvider 一起工作,您需要将 HandleSecurityAttribute code 复制到您的项目中并将其更改为从 AuthorizeAttribute 继承而不是 Attribute,然后按照 FluentSecurity 文档中的说明使用它。

    【讨论】:

      猜你喜欢
      • 2011-02-13
      • 2013-01-25
      • 1970-01-01
      • 1970-01-01
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 2014-11-04
      相关资源
      最近更新 更多