Tag Archives: SiteMap

web.sitemap – lokalizace a autorizace

Po chvilce bojů a objevení několika bugů se mi nakonec podařilo rozchodit lokalizaci a autorizaci v site-mapách ASP.NET, konkrétně při použití defaultního XmlSiteMapProvider a web.sitemap souborů (částečně to lze ovšem aplikovat i na jiné providery).

Lokalizace website.map

Defaultní XmlSiteMapProvider přímo podporuje lokalizaci web.sitemap souborů, stačí rootovému elementu nastavit atribut enableLocalization=“true“ a dále se pak na resources můžeme explicitně odkazovat obdobně jako v .aspx souborech, přes výraz $resources:ClassName,KeyName,DefaultValue

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" enableLocalization="true">
    <siteMapNode title="$resources: Navigation, UvodniStranka" url="~/default.aspx">
    ...
</siteMap>

Výše uvedený příklad by se opíral o soubor ~/App_GlobalResources/Navigation.resx. Jedná se o explicitní způsob lokalizace, existuje ještě implicitní metodika s využitím atributu resourceKey, nicméně implicitní lokalizace jako taková mě neoslovuje, takže ani tentokrát nebudu podorbněji rozvádět.

Pozor také, že mezi dolarem ($) a klíčovým slovem resources nesmí být mezerník. Lokalizovat lze výše uvedeným způsobem atributy title a description, bohužel ne url. Atribut url takto lokalizovat bohužel nelze, ač je to v některých dokumentacích uvedeno.

Pokud bychom chtěli lokalizovat i URL, můžeme to zařídit například tak, že nakonfigurujeme přes web.config dva nezávislé SiteMapProvidery, kde každý bude ukazovat na jiný .sitemap soubor:

<siteMap defaultProvider="CzXmlSiteMapProvider" enabled="true">
  <providers>
    <add name="CzXmlSiteMapProvider"
      description="Provider pro cestinu."
      type="System.Web.XmlSiteMapProvider"
      siteMapFile="WebCz.sitemap"
      securityTrimmingEnabled="true" />
    <add name="EnXmlSiteMapProvider"
      description="Provider pro cestinu."
      type="System.Web.XmlSiteMapProvider"
      siteMapFile="WebEn.sitemap"
      securityTrimmingEnabled="true" />
  </providers>
</siteMap>

…následně bychom podle aktuálního jazyka museli controlu SiteMapDataSource explicitně nastavovat příslušný SiteMapProvider (nastavit property SiteMapDataSource.SiteMapProvider, typ string). Deklaratorně například fíglem:

<asp:SiteMapDataSource
    ID="SiteMapDS"
    SiteMapProvider="<%$ Resources: Navigation, SiteMapProvider %>"
    runat="server" 
/>

Viz též obecná lokalizace webových aplikací.

Autorizace – skrývání uživateli nepřístupných položek

XmlSiteMapProvider, přesněji řečeno už bázová třída SiteMapProvider podporuje i authorizaci, resp. skrývání uživateli nedostupných položek. Tato funkčnost je řízena přes property SiteMapProvider.SecurityTrimmingEnabled, která se však nenastavuje programově (má jen get), nýbrž přes konfiguraci provideru z web.config souboru, atributem securityTrimmingEnabled:

<siteMap defaultProvider="MyXmlSiteMapProvider" enabled="true">
    <providers>
        <clear/>
        <add name="MyXmlSiteMapProvider"
         type="System.Web.XmlSiteMapProvider"
         siteMapFile="~/Web.sitemap"
         securityTrimmingEnabled="true" />
    </providers>
</siteMap>

Pokud nastavíme tento atribut, pravděpodobně nám začně funkčnost ihned fungovat. SiteMapProvider si sám hlídá přístupová práva uživatele nastavená přes sekci<authorization /> web.configu a uživateli nepřístupné položky skrývá.

Ovšem pozor!!! Implementace tohoto hlídání není úplně korektní a má problém s authorization pravidly web.config souborů, která se přes <location /> odkazují na podsložky. Chceme-li tedy tuto funkčnost SiteMapProvideru využít, můžeme ve web.config souborech definovat <location /> pravidla pouze pro jednotlivé soubory v příslušné složce a přístupová práva složek jako takových musíme řídit přes samostatné web.config soubory v těchto složkách!!!

Podle dokumentace a schématu .sitemap souboru má existovat u elementu <siteMapNode /> i atribut securityTrimmingEnabled, jakékoliv použití tohoto atributu však vyhazuje výjimku

ConfigurationErrorsException: Unrecognized attribute ‚securityTrimmingEnabled‘. Note that attribute names are case-sensitive.

Když jsem bádal v kódu XmlSiteMapProvideru, tak tam je tento atribut přímo zakázaný a zřejmě se jedná o nějaký přežitek z beta-verzí.

Element <siteMapNode /> má ještě atribut roles=“…“, kam lze explicitně nastavit, jakým uživatelským rolím se má node zobrazovat. Pokud však máme dobře nastavené samotné <authorization />, pak to mnohdy nepotřebujeme. Pokud ho přesto nastavíme, pak se vyhodnocuje MÍSTO standardních přístupových práv, nikoliv jako průnik.

Atribut roles=“*“ (nebo podobně) se nám bude hodit u externích odkazů, jejichž autorizaci nelze jinak vyhodnotit a bez explicitní volby roles se nám odkaz vůbec nezobrazí.

Dále je potřeba si uvědomit, že SiteMapProvider vyhodnocuje přístupová práva od rootu sitemap dolů a pokud nevyhoví nadřazená položka, ustřelí se celý podstrom. Například je tedy problematické bez dalšího použít prázdný atribut url=““, protože jeho přístupová práva není jak vyhodnotit a příslušný podstrom se tak nezobrazí – naopak je však možné do url dávat cestu k neexistujícím stránkám, vyhodnocení se provede, jako by existovali. Pokud potřebujeme udělat siteNode bez odkazu, pak musíme použít atribut roles=“…“, aby bylo přístupová práva jak vyhodnotit.

Související články