I was setting up permissions for pages in a ASP.NET website with <location>
tags in web.config, something similar to this:
<location path="Users.aspx">
<system.web>
<authorization>
<allow roles="Administrator"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
However, I also have a web.sitemap which basically contains the same information, i.e. which user roles can see/access which pages. A snippet from my web.sitemap:
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode title="Home">
... lots of nodes here ...
<siteMapNode url="users.aspx" roles="Administrator" title="users" description="Edit users" />
...
</siteMapNode>
</siteMap>
Is there 开发者_高级运维some kind of nifty way of using web.sitemap only to configure access? The <location>
tags are quite verbose, and I don't like having to duplicate this information.
Probably you're looking for SecurityTrimmingEnabled. See this forum post and blog entry for more details.
So Web.config
restricts access from direct URL typing and Web.sitemap
- from URLs being displayed
Sure, you can define a SiteMapProvider in your web.config, and use the CurrentNode property to get the SiteMapNode related to the requested page.
First declare your siteMap provider (web.config) :
<siteMap enabled="true" defaultProvider="DefaultXmlSiteMapProvider">
<providers>
<add siteMapFile="Web.sitemap" name="DefaultXmlSiteMapProvider" securityTrimmingEnabled="true" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</siteMap>
Sample code for page access control with CurrentNode (you can do it better ;)) :
bool hasAccess = false;
if (SiteMap.CurrentNode == null)
throw new ApplicationException("Page not present in SiteMap : " + this.Request.Url.AbsolutePath);
if (SiteMap.CurrentNode.Roles.Count > 0)
{
// All roles or no roles
if (SiteMap.CurrentNode.Roles.Contains("*") == true)
{
hasAccess = true;
}
else
{
for (int index = 0; index < SiteMap.CurrentNode.Roles.Count; index++)
{
string role = SiteMap.CurrentNode.Roles[index].ToString();
hasAccess = HttpContext.Current.User.IsInRole(role);
if (hasAccess == true)
break;
}
}
}
Note I added the everyone role (*), very usefull.
Here is the code of my own SiteMapProvider
which throws an exception where user being requested a page (node) has no right to do that (his role isn't in the list of node's roles)
public class XmlSiteMapProvider : System.Web.XmlSiteMapProvider
{
public override bool IsAccessibleToUser(HttpContext context, SiteMapNode node)
{
var roles = node.Roles.OfType<string>();
if (roles.Contains("*") || (roles.Count(r => context.User.IsInRole(r)) > 0))
{
return true;
}
else
{
throw new InsufficientRightsException();
}
}
}
To implement my own roles logic I also made my own RoleProvider
.
精彩评论