我刚刚注意到,在ASP.NET MVC 5.x站点中使用MVC Sitemap启用安全性调整会大大降低Web请求的速度。
我从documentation那里了解到,打开security trimming
时,MVC站点地图提供程序在站点地图中的每个控制器的实例上创建,以检查该节点对于当前节点是否可见用户(根据网络请求)。
我还read将每个Web请求都缓存,以将影响降到最低。
当我们的IoC框架将大多数控制器的依赖项管理为singleton
时,这种行为通常不会引起我们的注意(这意味着获得控制器的实例非常快)。
最近,我们的要求发生了变化,并且大多数依赖项都具有每个Web请求的生活方式,这对MVC Sitemap提供商的性能产生了巨大的负面影响: 在我们的开发机上,mvc网站地图需要花费5秒钟(!)来完成其工作(实例化所有构造函数)。
启用安全调整后,可以采取任何措施来加快速度吗?
注意:
也许值得一提的是,我们遵循在构造函数应用程序中不执行任何操作的最佳做法,即将参数分配给实例变量或属性,以避免进一步降低速度。
我们还坚持使用Microsoft提供的默认Authorize属性。
答案 0 :(得分:0)
这是我最终实现的解决方案:
restrict-to-role
,该节点与用[Authorize(Roles="Role1,Role2")]
属性修饰的控制器动作匹配。restrict-to-roles
属性。如果有值,则调用ASP.NET身份的IsInRole
方法来检查当前用户是否可以看到该节点。public class RolesInXmlFileSecurityTrimmingVisibilityProvider : SiteMapNodeVisibilityProviderBase
{
public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
var isVisible = true;
if (node.Attributes.ContainsKey("restrict-to-roles"))
{
var roles = Convert.ToString(node.Attributes["restrict-to-roles"]);
if (!string.IsNullOrEmpty(roles))
{
// Your implemenation may vary
isVisible = IsInRole(roles);
}
}
return isVisible;
}
}
优势:
这非常快,您无需实例化所有控制器来寻找[Authorize]
属性。
缺点:
您必须在控制器中MVC restric-to-roles
顶部的MVC站点地图文件中手动维护[Authorize]
属性。
答案 1 :(得分:0)
@bounav,谢谢,谢谢,谢谢!虽然不是一个理想的解决方案,但它确实有效,而且节省的时间/处理过程确实会对我的客户产生巨大的影响/差异。
虽然基于上面的解决方案,我实现的代码差异很大。我会在这里发布关键部分,希望对其他人有所帮助。
变更摘要 此实现使用线程原理 (IPrincipal)。有一些调整可以处理多个角色以及使用 [Authorize] 属性而没有任何特定角色的控制器(用户只需要经过身份验证)。我将属性的名称从“restrict-to-roles”更改为“Roles”。这允许我简单地将每个控制器的 [Authorize] 属性中的值复制/粘贴到 Mvc.sitemap XML 文件中。例如这个控制器属性:
[Authorize(Roles = "YourSecurityRole")]
在 Mvc.sitemap XML 文件中变成这个:
<mvcSiteMapNode title="Your Title" controller="Yourcontroller" Roles = "YourSecurityRole" action="YourControllerAction" key="YourNodeKey">
这是相关的类:
public class RolesInXmlFileSecurityTrimmingVisibilityProvider : SiteMapNodeVisibilityProviderBase
{
public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
// If the sitemap node does not contain the 'roles' attribute, simply return true.
if (!node.Attributes.ContainsKey("Roles"))
{
return true;
}
// When the sitemap node contains the 'roles' attribute, the user must at least be authenticated for the node to be visible.
var currentUser = Thread.CurrentPrincipal;
if (currentUser == null || currentUser.Identity == null || currentUser.Identity.IsAuthenticated == false)
{
return false;
}
var strRoles = Convert.ToString(node.Attributes["Roles"]);
if (string.IsNullOrWhiteSpace(strRoles))
{
return true; // Use an empty Roles="" attribute/value for controllers with only the basic [Authorize] attribute
}
else
{
var arrRoles = strRoles.Split(',');
foreach (var role in arrRoles)
{
if (currentUser.IsInRole(role))
{
return true; // The authenticated user matches at least one of the roles required for visibility.
}
}
}
return false; // The authenticated user did not match any of the roles required for visibility.
}
}
由于我们使用了 Ninject DI,我还想提及另外三个值得注意的技术细节。
使用 NinjectModule 作为基类的“MvcSiteMapProviderModule”是我禁用安全修整的地方。重写的 Load() 方法,摘录:
bool securityTrimmingEnabled = false;
// Configure the builder sets .Kernel.Bind<ISiteMapBuilderSet>().To<SiteMapBuilderSet>().Named("siteMapBuilderSet1").WithConstructorArgument("instanceName", "default").WithConstructorArgument("securityTrimmingEnabled", securityTrimmingEnabled)...<removed for brevity>
用于“ISiteMapNodeVisibilityProviderStrategy”的类必须按如下方式换出:
this.Kernel.Bind<ISiteMapNodeVisibilityProviderStrategy>().To<SiteMapNodeVisibilityProviderStrategy>() .WithConstructorArgument("defaultProviderName", "YourNamespace.RolesInXmlFileSecurityTrimmingVisibilityProvider, YourAssemblyName");
除非您希望 URL 中出现额外的“Roles”属性,否则您必须这样配置“attributesToIgnore”值:
// Prepare for our node providers this.Kernel.Bind<IXmlSource>().To<FileXmlSource>().Named("XmlSource1") .WithConstructorArgument("fileName", absoluteFileName);
this.Kernel.Bind<ISiteMapXmlReservedAttributeNameProvider>().To<SiteMapXmlReservedAttributeNameProvider>().Named("xmlBuilderReservedAttributeNameProvider").WithConstructorArgument("attributesToIgnore", new string[1] { "Roles" });
希望有所帮助!