1

我一直在使用MVCSiteMap设置我的菜单我有这样的节点:MVCSiteMap节点Requring多重角色

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

我试图强制执行,这点必须有角色“CORLIC” AND“VIEWCOBO”为它是可见的,但当然这意味着如果用户具有上述任何一个,它将被显示。

这可能吗?

谢谢。

回答

1

roles属性用于与ASP.NET的互操作性,不应仅用于MVC专用应用程序。

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

[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); 
} 

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