我正在使用MVC5,Windows身份验证,结构图DI和自定义角色提供程序。
MVC5的MvcSiteMapProvider没有根据用户角色选择显示菜单的角色。启用安全修整后,它仅显示未定义任何角色属性的菜单项。
我已在控制器上实现并使用ActionFilterAttribute进行授权。控制器根据角色正确地将用户重定向到未经授权的页面,但是菜单没有选择角色属性来隐藏菜单。
自定义RoleProvider具有GetRolesForUser和GetUsersInRole的实现。
任何建议都会有所帮助。
还想知道在SiteMapNodeModel中查找角色属性的位置。我正在考虑自定义在构建菜单时在HtmlHelper中查找权限。
注意:相同的实现在MVC4中正常工作。一旦升级到MVC5并且它不起作用。
由于
答案 0 :(得分:1)
MVC5的MvcSiteMapProvider没有根据用户角色选择显示菜单的角色。启用安全修整后,它仅显示未定义任何角色属性的菜单项。
根据the documentation,roles属性不适用于MVC。它用于与ASP.NET页面互操作。
它仅在安全框架实现IPrincipal
和IIdentity
作为成员身份和身份时才起作用。
我已在控制器上实现并使用ActionFilterAttribute进行授权。控制器根据角色正确地将用户重定向到未经授权的页面,但是菜单没有选择角色属性来隐藏菜单。
这很可能是您的问题。安全修整仅查找AuthorizeAttribute
和AuthorizeAttribute
的子类。如果您有子ActionFilterAttribute
,则不会将其用于隐藏导航中的链接。
当然,要使标准AuthorizeAttribute
起作用,您需要实现IPrincipal
和IIdentity
或使用其中一个预先构建的安全框架。
或者,如果您具有完全自定义的安全性,则可以构建自己的IAclModule
或ISiteMapNodeVisibilityProvider
。
还想知道在SiteMapNodeModel中查找角色属性的位置。我正在考虑自定义在构建菜单时在HtmlHelper中查找权限。
您无需从SiteMapNodeModel
查找角色。相反,您应该从当前上下文中获取角色,并相应地对/Views/Shared/DisplayTemplates/
中的菜单模板进行更改。
如果您使用的是支持IPrincipal
和IIdentity
的框架,则可以使用:
@if (User.IsInRole("SomeRole"))
{
...
}
另见:
如果要获取为操作方法配置的当前角色,可以构建扩展方法以从当前AuthorizeAttribute
读取角色。同样,roles
属性仅用于与ASP.NET的互操作性,不应用于纯MVC,因为这意味着您需要在AuthorizeAttribute
上复制角色。
public static class ControllerContextExtensions
{
public static IEnumerable<string> Roles(this ControllerContext controllerContext)
{
var controllerType = controllerContext.Controller.GetType();
var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
var actionName = controllerContext.RouteData.Values["action"] as string;
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
var authorizeAttribute = FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor)
.Where(f => typeof(AuthorizeAttribute).IsAssignableFrom(f.Instance.GetType()))
.Select(f => f.Instance as AuthorizeAttribute).FirstOrDefault();
string[] roles = { };
if (authorizeAttribute != null && authorizeAttribute.Roles.Length > 0)
{
roles = Array.ConvertAll(authorizeAttribute.Roles.Split(','), r => r.Trim());
}
return roles;
}
}
在视图中:
{ var roles = this.ViewContext.Controller.ControllerContext.Roles(); }
在控制器中:
var roles = this.ControllerContext.Roles();
SiteMapNodeModel
: var siteMap = MvcSiteMapProvider.SiteMaps.Current;
var siteMapNode = siteMap.FindSiteMapNodeFromKey(SiteMapNodeModel.Key);
var roles = siteMapNode.Roles;