我使用MVCSiteMap设置了菜单,我有这个节点:
<mvcSiteMapNode title="Courses Form" controller="Booking" action="Course" roles="CORLIC, VIEWCOBO"/>
我正在尝试强制执行此节点必须具有“CORLIC”和“VIEWCOBO”角色才能看到它,但这当然意味着如果用户具有上述任一项,它将会显示。
这可能吗?
感谢。
答案 0 :(得分: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接受角色,但它的工作方式与roles属性相同 - 也就是说,用户所在的任何角色都会使其成功。
但是,您可以自己继承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文档中的指定使用它。