17

WCF pro začátečníky – 8. díl: Autentizace podruhé

autor Kryštof Laryš | publikováno 16. září 2010


Možností, jak implementovat autentizaci ve WCF je hned několik. My si popíšeme dvě z nich. Autentizaci pomocí ASP.NET Membership Provider a Custom Membership Provider. V tomto díle to bude Custom Membership Provider. V díle minulém to byl ASP.NET Membership Provider.

Poznámka na úvod: Některá slovíčka, jako je třeba user name, password, credentials, membership, provider atd., záměrně překládám, většinou je ale ponechávám nepřeložené už z toho důvodu, že mi to tak příjde jasnější. Navíc se často stává, že v konfiguračním souboru se element jmenuje anglicky přesně tak, jak se tato slovíčka normálně píší, proto je většinou nepřekládám.

Autentizace pomocí Custom Membership Provider
K čemu je vůbec Custom Membership dobré? Použijeme jej, pokud nám nastavení či styl, funkčnost apod. u již vytvořených Membership nevyhovuje. Představme si, že tvoříme webovou aplikaci, kde chceme, aby se určitý obsah zobrazoval pouze některým uživatelům. Jde jen o pohled na věc, zda zde použít Custom Membership provider. Předpokládáme, že webová prezentace by měla být co nejvíce bezestavová a požadujeme, aby se autentizace prováděla při každém volání služby, posílání a vrácení zpráv atd. Toto se může zdát jako nadbytečná režie, stále zpracovávat to samé dokola. Uvědomme si ale, že udržování stavů s sebou nese podstatné nevýhody a hlavně problémy spojené s autentizací. Například jak poznáme, kdy máme zrušit platnost kešované kopie přihlašovacích údajů? Či co když uživatel ukončí aplikaci, ale cookie stále zůstane na jeho počítači? Minimálně z těchto důvodů bych se udržování stavů vyhnul. To se ale samozřejmě týká autentizačních údajů, nikoliv udržování stavů obecně.

Pokud bychom i tak chtěli využít stavů, použili bychom tzv. mód kompatibility ASP.NET (ASP.NET compatibility mode). Ten nám sice zpřístupní přístup k HttpContext, na druhou stranu nás ale limituje tím, že danou službu spustíme pouze v IIS. Pro zapnutí kompatibilního módu upravíme web.config následujícím způsobem:

 <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

Ještě je nutné upravit nastavení třídy služby, a to takto:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1 : IService1

Podívejme se na nastavení služby a implementaci našeho vlastního Custom Membership providera. Ať už zapnu ASP.NET kompatibilitu či nikoliv, vrhnu se na implementaci vlastní třídy. Vytvořím si novou class library, na kterou budu v projektu služby vytvářet referenci. Projekt pojmenuji Provider a samotnou knihovnu nazvu MyCustomMembershipProvider. Abych nyní mohl implementovat své nové rozhraní Custom Membership providera, musím dědit z rozhraní MembershipProvider. K tomu ale ještě do projektu potřebuji přidat referenci na knihovnu System.Web.Security. Samotná naše nově vytvořená knihovna by tedy měla vypadat zhruba takto:

using System;
using System.Web.Security;
namespace Provider
{
    public class MyCustomMembershipProvider : MembershipProvider
    {
        public override bool EnablePasswordRetrieval
        {
            get { throw new NotImplementedException(); }
        }

 V této třídě si můžeme upravit jakoukoli metodu, kterou budeme chtít a vytvoříme tím vlastního providera. Já pro jednoduchost upravil metodu ValidateUser takto: 

public override bool ValidateUser(string username, string password)
        {
            return (username.Equals("admin")
                    && password.Equals("admin"));
        }

To je konkrétně jednoduchý příklad, kdy na samotné webové stránce testuji, zda se uživatel přihlásil s přihlašovacími údaji takovými, že uživatelské jméno je admin a heslo taktéž admin.

 Dalším krokem je upravení souboru Web.config služby. Upravíme element <system.web> následujícím způsobem:

<system.web>
    <globalization uiCulture="en" culture="en-GB" />
    <!--<identity impersonate="true"/>-->
    <authentication mode="None" />
    <membership defaultProvider="MyCustomMembershipProvider">
      <providers>
        <clear />
        <add name="MyCustomMembershipProvider" type="Provider.MyCustomMembershipProvider,Provider" />
      </providers>
    </membership>

Všimněme si, kde je podobnost s minulým dílem seriálu o autentizaci a kde se přesně píše název oboru názvů a název třídy našeho vlastního providera. Dále si všimněme hned druhého elementu globalization. Ten přímo nesouvisí s autentizací, ale mám ho zde uvedený z důvodu, že ladění webových služeb není zrovna jednoduché a chybové hlášky nám v češtině toho často moc nepoví, proto se všechny chybové hlášky budou zobrazovat v anglickém jazyce. Nám pak jen stačí zkopírovat chybové hlášení do googlu a hledat odpověď. ;-)

Podobnost s autentizací z minulého dílu je i v bodě nastavení konfigurace chování služby. Přesněji elementu <serviceCredentials>.

<serviceCredentials>
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
            <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="MyCustomMembershipProvider" />
</serviceCredentials>

Další věc, na kterou bychom měli myslet, je nastavení konfiguračního souboru u služby, ve které pracujeme s přihlašovacími údaji, ale která nám slouží jako klientská aplikace (webová prezentace), ne jako hostovací služba. Na tomto místě už budeme chtít konkrétně ověřovat uživateli zadávané přihlašovací údaje. Provedeme to například následujícím způsobem:

<system.web>
    <globalization uiCulture="en" culture="en-GB"/>
    <!--<identity impersonate="true"/>-->
    <authentication mode="Forms">
      <forms name=".ASPXFORMSAUTH" loginUrl="Login.aspx"/>
    </authentication>
    <authorization>
      <deny users="?"/>
    </authorization>
    <membership defaultProvider="MyCustomMembershipProvider">
      <providers>
        <clear/>
        <add name="MyCustomMembershipProvider" type="Provider.MyCustomMembershipProvider,Provider"/>
      </providers>
    </membership>

Konfigurační soubor jistě mluví sám za sebe. Snad dovysvětlení elementu <deny users="?"/>, kde otazník nám zajišťuje, že na stránky nebude mít přístup žádný nepřihlášený uživatel. Na stránce Login.aspx nezapomeňme vytvořit ovládací prvek Login.


Kryštof