ASP.NET web.sitemap - 角色似乎无法控制可见性?

发布于 2024-08-26 07:31:41 字数 2510 浏览 5 评论 0原文

我有一个(简单的)站点地图,并试图找出为什么某个子菜单总是可见。

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
  <siteMapNode url="~/Login.aspx" title="Home" description="RivWorks" roles="*">
    <siteMapNode url="" title="Dashboard" description="" roles="campaigns, auto_negotiation">
      <siteMapNode url="CampaignBuilder.aspx" title="Campaign Manager" description="Manage your campaign settings" roles="campaigns" />
      <siteMapNode url="ProductManager.aspx" title="Negotiation Manager" description="Manage your product and negotiation settings" roles="auto_negotiation" />
    </siteMapNode>
    <siteMapNode url="" title="Support Options" description="" roles="customers, customer_super, riv_admins, riv_super">
      <siteMapNode url="ChangePassword.aspx" title="Change Password" description="" roles="customers, customer_super, riv_admins, riv_super" />
      <siteMapNode url="http://rivworks.zendesk.com/requests/anonymous/new" title="Submit a Support Ticket" description="" roles="customers, customer_super, riv_admins, riv_super" />
      <siteMapNode url="http://rivworks.zendesk.com/forums/49919/entries" title="Tips &amp; Tricks" description="" roles="customers, customer_super, riv_admins, riv_super" />
    </siteMapNode>
  </siteMapNode>
</siteMap>


NOTE: WEB.CONFIG SETTINGS

<siteMap defaultProvider="XmlSiteMapProvider" enabled="true">
  <providers>
    <add name="XmlSiteMapProvider"
         description="Default Site Map Provider"
         type="System.Web.XmlSiteMapProvider"
         siteMapFile="Web.sitemap"
         securityTrimmingEnabled="true" />
  </providers>
</siteMap>


I have a main menu option of "Dashboard". Under this menu item I have 2 options: 1) Campaign Manager & 2) Negotiation Manager. Now, what is interesting is when I am in either the campaigns role OR the auto-negotiation role I see the Dashboard and BOTH sub-menu items. This is not the behavior I expected. I expect to only see both sub-menus when I am in the campaigns role AND auto-negotiation role. The OR scenario should give me the Dashboard menu item and one OR the other sub-item...

我在这里做错了什么或者以错误的方式思考吗?

TIA

I have a (simple) sitemap and am trying to figure out why a certain sub-menu is always visible.

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
  <siteMapNode url="~/Login.aspx" title="Home" description="RivWorks" roles="*">
    <siteMapNode url="" title="Dashboard" description="" roles="campaigns, auto_negotiation">
      <siteMapNode url="CampaignBuilder.aspx" title="Campaign Manager" description="Manage your campaign settings" roles="campaigns" />
      <siteMapNode url="ProductManager.aspx" title="Negotiation Manager" description="Manage your product and negotiation settings" roles="auto_negotiation" />
    </siteMapNode>
    <siteMapNode url="" title="Support Options" description="" roles="customers, customer_super, riv_admins, riv_super">
      <siteMapNode url="ChangePassword.aspx" title="Change Password" description="" roles="customers, customer_super, riv_admins, riv_super" />
      <siteMapNode url="http://rivworks.zendesk.com/requests/anonymous/new" title="Submit a Support Ticket" description="" roles="customers, customer_super, riv_admins, riv_super" />
      <siteMapNode url="http://rivworks.zendesk.com/forums/49919/entries" title="Tips & Tricks" description="" roles="customers, customer_super, riv_admins, riv_super" />
    </siteMapNode>
  </siteMapNode>
</siteMap>


NOTE: WEB.CONFIG SETTINGS

<siteMap defaultProvider="XmlSiteMapProvider" enabled="true">
  <providers>
    <add name="XmlSiteMapProvider"
         description="Default Site Map Provider"
         type="System.Web.XmlSiteMapProvider"
         siteMapFile="Web.sitemap"
         securityTrimmingEnabled="true" />
  </providers>
</siteMap>


I have a main menu option of "Dashboard". Under this menu item I have 2 options: 1) Campaign Manager & 2) Negotiation Manager. Now, what is interesting is when I am in either the campaigns role OR the auto-negotiation role I see the Dashboard and BOTH sub-menu items. This is not the behavior I expected. I expect to only see both sub-menus when I am in the campaigns role AND auto-negotiation role. The OR scenario should give me the Dashboard menu item and one OR the other sub-item...

Am I doing something wrong here or thinking a wrong way?

TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

征﹌骨岁月お 2024-09-02 07:31:41

我怀疑您已经陷入了我们都犯过的陷阱,相信角色属性限制了节点的可见性。事实并非如此,它实际上扩大了可见性。所有限制均通过 web.config 中的标准部分完成。

下面的全文来自原始帖子 https://web.archive.org/web/20130408064047/http://ipona.com/asp-net-site-maps-security-trimming-and-roles/ )

这是最常见的问题之一,似乎一直是每个人困惑的根源,就像我第一次读到它时一样。 ASP.NET SiteMap 允许将导航结构定义为一组 XML 元素,这非常适合描述菜单项的层次结构。这些 XML 项是一个 siteMapNode 元素,它具有一个属性 Roles。看起来很明显,这定义了可以看到该项目的角色,但这种明显的事实实际上是错误的。这是关于站点地图的最重要的事实:

角色属性不限制节点的可见性。

这应该足够清楚,即使它看起来仍然是错误的。这是它的工作原理。
对页面的所有限制都是通过授权处理的。您可以在基本 web.config 或文件夹中的 web.config 文件中执行此操作。例如,假设有一个 Admin 文件夹,所有管理页面都保存在该文件夹下。您只希望具有管理员角色的用户可以访问这些页面。您可以像这样配置您的授权:

<location path="Admin">
  <system.web>
    <authorization>
      <allow roles="Admin" />
      <deny users="*" />
    </authorization>
  </system.web>
</location>

Admin 文件夹现在不能再被任何不属于 Admin 角色的人访问;如果您不是管理员角色,并尝试通过另一个页面上的链接或直接在浏览器中输入 URL 导航到 Admin 文件夹中的页面,您将被重定向到登录页面。您的 web.config 中可以有多个位置元素,用于不同的文件夹甚至单个文件;事实上,如果您有一个限制性站点,您可能希望明确打开某些页面,例如登录页面;当您没有访问登录页面的授权时,很难登录到站点。如果您不想让您的基本 web.config 变得混乱,您可以使用相同的规则在 Admin 文件夹中创建一个 web.config 文件;您不需要 location 元素,因为配置适用于当前文件夹。

这样授权就完成了;对页面的访问被锁定。现在让我们考虑导航。 ASP.NET 导航框架会尊重授权,但前提是您在提供程序上配置安全调整(默认情况下未配置)。这意味着您需要将站点地图配置添加到 web.config:

<siteMap enabled="true" defaultProvider="AspXmlSiteMapProvider">
  <providers>
    <clear />
    <add name="AspXmlSiteMapProvider" securityTrimmingEnabled="true"
     type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
     siteMapFile="web.sitemap"/>
  </providers>
</siteMap>

其中大部分是在安装 ASP.NET 时在计算机级别配置的,但关键的是 securityTrimmingEnabled 值默认设置为 false。上面的作用是清除现有配置并添加一个属性设置为 true 的新条目。在此阶段,导航框架将遵守授权规则,因此如果用户没有该菜单项的授权,则不会显示该菜单项;如果您使用 Menu 或 TreeView 来显示菜单项并不重要,关键部分是使用 SiteMapDataSource(如果您手动构建菜单,则使用 Sitemap API)。如果您有一个自定义站点地图提供程序,例如数据库驱动的提供程序(例如 MSDN 上的这个提供程序),那么这可能必须执行其自己的安全检查,但这取决于您继承的基类。不过,这是另一篇文章的另一个故事了。

那么,如果您不需要修改站点地图元素本身,那么 Roles 属性有什么用呢?好吧,这与您可能期望的相反方式工作,通过打开节点的可见性,即使用户没有访问页面本身的授权(因为授权规则限制他们),也可以显示节点是否处于指定的角色从访问它)。你为什么要这样做?好吧,您必须了解安全调整的工作原理。当决定用户是否可以看到节点时,会检查授权和物理文件权限;如果任一失败,则该节点被视为不可访问。物理文件检查失败有两种常见情况:

  1. URL 不是本地的。如果该文件在本地不存在,则无法进行检查。
  2. 没有网址。该节点可以只是一个容器节点,具有子页面但没有页面本身。

在这两种情况下,物理文件检查都会失败,因此不会显示节点。因此,您可能需要打开节点的可见性。例如,请考虑以下情况:

<siteMapNode title="Admin" roles="Admin">
    <siteMapNode url="~/Admin/membership_CreateMember.aspx" title="Create User" />
    <siteMapNode url="~/Admin/membership_GetUsers.aspx" title="View Users" />
    <siteMapNode url="~/Admin/roleManager_CreateRole.aspx" title="Create Role" />
    <siteMapNode url="~/Admin/roleManager_AddUserToRole.aspx" title="Add User to Role" />
</siteMapNode>

这里的管理节点没有物理页面,它纯粹是为了允许将管理项目组织到它们自己的子菜单中。如果没有附加的 Roles 属性,节点和子节点将不会出现,但 Roles=”Admin” 声明该节点也应该向 Admin 角色内的用户显示,即使安全检查失败也是如此。我们不需要子节点上的属性,因为它们有物理页,因此文件检查将会成功。

因此,如果您记住规则,那就相当简单了:

  • 在具有授权的页面上配置安全限制
    网络配置。
  • 重新定义站点地图提供商,实现安全性
    修剪。
  • 将角色属性添加到站点地图节点以扩大范围
    能见度。

I suspect you've fallen into the trap we all do, in believing that the roles attribute restricts visibility of the nodes. It doesn't, it actually widens visibility. All restrictions are done with the standard section in web.config.

Full text below is from original post at https://web.archive.org/web/20130408064047/http://ipona.com/asp-net-site-maps-security-trimming-and-roles/ )

This is one of the most frequently asked questions and seems a constant source of confusion for everyone, as it was for me when I first read about it. The ASP.NET SiteMap allows a navigational structure to be defined as a set of XML elements, which are perfect for describing a hierarchy of menu items. These XML items are a siteMapNode element, which has an attribute roles. It seems obvious that this defines the roles that can see this item, but the obvious is in fact wrong. Here is the most important fact about site maps:

The roles attribute does not restrict visibility of a node.

That should be clear enough, even if it still seems wrong. Here’s how it works.
All restriction to pages is handled via authorization. You can do this either in the base web.config, or in web.config files in folders. For example, assume there is an Admin folder, under which all the administration pages are kept. You only want these pages accessible to users within the Admin role. You would configure your authorization like so:

<location path="Admin">
  <system.web>
    <authorization>
      <allow roles="Admin" />
      <deny users="*" />
    </authorization>
  </system.web>
</location>

The Admin folder can now no longer be accessed by anyone who is not in the Admin role; if you aren’t in the Admin role and try to navigate to a page in the Admin folder, either via link on another page or by typing the URL directly into the browser, you’ll be redirected to the login page. You can have multiple location elements in your web.config, for different folders or even individual files; in fact if you have a restrictive site, you may want to explicitly open up certain pages, such as the login page; it’s hard to login to a site when you don’t have authorization to access the login page. If you prefer not to clutter your base web.config you can create a web.config file in the Admin folder with the same rules; you won’t need the location element since the configuration applies to the current folder.

So that’s authorization done; access to the pages is locked down. Now lets consider navigation. The ASP.NET navigation framework honours the authorization, but only if you configure security trimming on the provider, which isn’t configured by default. This means that you need to add the site map configuration to web.config:

<siteMap enabled="true" defaultProvider="AspXmlSiteMapProvider">
  <providers>
    <clear />
    <add name="AspXmlSiteMapProvider" securityTrimmingEnabled="true"
     type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
     siteMapFile="web.sitemap"/>
  </providers>
</siteMap>

Most of this is configured at the machine level when ASP.NET is installed, but crucially the securityTrimmingEnabled value is set to false by default. What the above does is clear out the existing configuration and add a new entry with the attribute set to true. At this stage the navigation framework will now honour the authorization rules, so menu items won’t be shown if the user doesn’t have authorization for that item; it doesn’t matter if you use a Menu or TreeView to display the menu items, the crucial part is using the SiteMapDataSource (or the Sitemap API if you’re building the menu manually). If you have a custom site map provider, such as a database driven one (such as this one on MSDN), then this might have to do it’s own security checking, but it depends at which base class you inherit from. That’s another story for another post though.

So if you don’t need to modify the site map elements themselves, what’s the roles attribute for? Well this works in the opposite way you probably expect, by opening up visibility of the node, showing the node if the user is in the stated role even if they don’t have authorization to access the page itself (because the authorization rule restrict them from accessing it). Why would you do this? Well, you have to understand how security trimming works. When deciding whether a user can see a node, both the authorization and the physical file permissions are checked; if either fail then the node is deemed inaccessible. There are two very common times when physical file checks fail:

  1. The URL isn’t local. If the file doesn’t exist locally then no check can take place.
  2. There isn’t a URL. The node could be just a container node, with child pages but no page itself.

In both of these cases the physical file checks fail so the node won’t be shown. You therefore may need to open up the visibility of the node. For example, consider the following:

<siteMapNode title="Admin" roles="Admin">
    <siteMapNode url="~/Admin/membership_CreateMember.aspx" title="Create User" />
    <siteMapNode url="~/Admin/membership_GetUsers.aspx" title="View Users" />
    <siteMapNode url="~/Admin/roleManager_CreateRole.aspx" title="Create Role" />
    <siteMapNode url="~/Admin/roleManager_AddUserToRole.aspx" title="Add User to Role" />
</siteMapNode>

Here the Admin node doesn’t have a physical page, it’s purely to allow organisation of the admin items into their own submenu. Without the additional roles attribute the node and children wouldn’t appear, but roles=”Admin” states that the node should also be shown to users within the Admin role, even if the security checking fails. We don’t need the attribute on the child nodes because they have physical pages, so the file checks will succeed.

So it’s fairly straightforward if you remember the rules:

  • Configure security restrictions on pages with authorization in
    web.config.
  • Redefine the site map provider, enabling security
    trimming.
  • Add the roles attribute to site map nodes to widen the
    visibility.
雪落纷纷 2024-09-02 07:31:41

您想要的是 ASP.NET 所指的“站点地图安全修剪< /a>”。您已经完成了大部分工作 - 即为站点地图中的节点分配角色。现在,您所要做的就是进行一些配置。

web.config 中,使用标准 XmlSiteMapProvider 添加新的站点地图提供程序,但使用 securityTrimmingEnabled="true",并将其设为默认提供商:

<system.web>
  <siteMap defaultProvider="XmlSiteMapProvider" enabled="true">
    <providers>
      <add name="TrimmedSitemap"
        type="System.Web.XmlSiteMapProvider"
        siteMapFile="Web.sitemap"
        securityTrimmingEnabled="true" />
    </providers>
  </siteMap>
</system.web>

What you want is what ASP.NET refers to as "Site-Map Security Trimming". You have already done most of the work - namely assigning roles to the nodes in the sitemap. Now, all you have left to do, is a bit of configuration.

In your web.config, add a new site map provider using the standard XmlSiteMapProvider, but with securityTrimmingEnabled="true", and make this the default provider:

<system.web>
  <siteMap defaultProvider="XmlSiteMapProvider" enabled="true">
    <providers>
      <add name="TrimmedSitemap"
        type="System.Web.XmlSiteMapProvider"
        siteMapFile="Web.sitemap"
        securityTrimmingEnabled="true" />
    </providers>
  </siteMap>
</system.web>
凝望流年 2024-09-02 07:31:41

我知道这是非常旧的,但我继承了一些旧代码并遇到了同样的问题。我的老板希望我暂时隐藏单个角色的功能可见性,但仍然可以在网站的其他地方访问它。我完全希望从站点地图中删除该角色,并且该角色对此不可见。埃里克清楚地解释了它的目的是如何提高可见性而不是限制。

我只是想举一个例子,说明如何使其按照您(和我)期望的方式运行(角色必须出现在两个地方)。

<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1" OnMenuItemDataBound="Menu1_TreeNodeDataBound" />

protected void Menu1_TreeNodeDataBound(object sender, MenuEventArgs e)
{
    if (e.Item.DataItem!=null && ((SiteMapNode)e.Item.DataItem).Roles.Count > 0 && HttpContext.Current.User.Identity.IsAuthenticated)
    {
        string role = Common.GetUserRole();  // I have a single role provider and a common function to get the role.  You could always loop through Roles and use HttpContext.Current.User.IsInRole()         
        if (role.Length > 0)
        {
            if (!((SiteMapNode)e.Item.DataItem).Roles.Contains(role))
            {
                if (e.Item.Parent != null)
                    e.Item.Parent.ChildItems.Remove(e.Item);
                else
                    Menu1.Items.Remove(e.Item);
            }
        }            
    }
}

I know this is super old but I inherited some old code and came across the same problem. My boss wanted me to temporarily hide a features visibility from a single role but still make it accessible elsewhere on the site. I fully expected to just remove the role from the sitemap and it not be visible to this role. Eric explained clearly how it's intended to increase visibility rather than limit.

I just wanted to give an example of how to make it function the way you(and I) were expecting it to function(role must be present in both places).

<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1" OnMenuItemDataBound="Menu1_TreeNodeDataBound" />

protected void Menu1_TreeNodeDataBound(object sender, MenuEventArgs e)
{
    if (e.Item.DataItem!=null && ((SiteMapNode)e.Item.DataItem).Roles.Count > 0 && HttpContext.Current.User.Identity.IsAuthenticated)
    {
        string role = Common.GetUserRole();  // I have a single role provider and a common function to get the role.  You could always loop through Roles and use HttpContext.Current.User.IsInRole()         
        if (role.Length > 0)
        {
            if (!((SiteMapNode)e.Item.DataItem).Roles.Contains(role))
            {
                if (e.Item.Parent != null)
                    e.Item.Parent.ChildItems.Remove(e.Item);
                else
                    Menu1.Items.Remove(e.Item);
            }
        }            
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文