Меню на основе ролей не работает, что я делаю не так?
Я не могу понять это.
У меня есть следующая карта сайта
<?xml version="1.0" encoding="utf-8" ?> <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" > <siteMapNode url="~/" title="Root" description="Go root"> <siteMapNode url="~/h" title="Home" description="Go home" /> <siteMapNode url="~/h/uo" title="Ultima Online" description="Ultima Online"> <siteMapNode url="~/h/uo/get" roles="RegisteredUser" title="Get account!" description="Get account!" /> </siteMapNode> </siteMapNode> </siteMap>
У меня есть
XmlSiteMapProvider
сsecurityTrimmingEnabled="true"
, который указывает на этот файл карты сайта.Файл, который я хочу обрезать, имеет
authorization
править в своей папкеweb.config
<configuration> <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </configuration>
Файл не может быть доступен через URL, если я наберу
http://localhost/h/uo/get
Я перенаправлен на страницу входа.Я создал
<asp:Menu>
вот так в файле главной страницы:<asp:SiteMapDataSource ID="MenuSiteMap" ShowStartingNode="false" SiteMapProvider="MenuSiteMapProvider" runat="server" /> <div> <asp:Menu ID="NavigationMenu" runat="server" DataSourceID="MenuSiteMap" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal" /> </div>
Тем не менее, когда страница отображается, я вижу Get account
узел, который должен быть обрезан, когда я даже не вошел в систему, несмотря ни на что.
- Что я делаю неправильно?
- Есть ли какой-либо другой способ построить меню навигации с поддержкой настройки безопасности?
Я использую ASP.NET 4.0 и перезаписываю URL с помощью HttpModule.
1 ответ
Читая http://forums.asp.net/t/975077.aspx/1 я узнал, что это именно то, что со мной происходит.
Если у узла нет URL-адреса, он ведет себя нормально, но если он есть, как и у всех моих узлов. Обрезка безопасности просто игнорируется.
Я решил свою проблему, прибегнув к более интуитивной реализации карты сайта на основе ролей:
public class TrimmingXmlSiteMapProvider : XmlSiteMapProvider
{
public override bool IsAccessibleToUser(HttpContext context, SiteMapNode node)
{
if (node.Roles.Cast<string>().Any(r => r == "*"))
return true;
if (node.Roles.Count > 0 && node.Roles.Cast<string>().Count(Roles.IsUserInRole) == 0)
return false;
return node.ParentNode != null && node.ParentNode.IsAccessibleToUser(context);
}
}
Затем единственное изменение, которое я должен был сделать, это добавить звездочку в определение роли корневого уровня.
Как это работает?
Сначала я проверяю, является ли какая-либо из ролей, определенных для этого узла, звездочкой, если это так, то я вижу узел.
Во-вторых, если узел не для всех пользователей, я проверяю, указаны ли какие-либо роли и входит ли пользователь, вошедший в систему, хотя бы в одну из них.
Наконец, я проверяю, есть ли родительский узел, и просто наследую их правило.
Это позволяет обрезать параметры безопасности на самом деле "ОБЕСПЕЧЕНИЕ БЕЗОПАСНОСТИ" и не очень хорошо, однако, черт возьми, он должен работать по умолчанию.