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>
<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>
Am I doing something wrong here or thinking a wrong way?
TIA
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:
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:
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With