Správa uživatelů v ASP.NET 2.0
I tentokrát se podíváme na další novinky v novém .NET, konkrétně postupy okolo přihlašování a správy uživatelů. V tomto článku se zaměřím spíše na tu praktickou část, abyste mohli co nejdříve začít vytvářet aplikace.
Správa uživatelů v novém .NETu je založena na takzvaném Provider modelu. Díky tomu není potřeba pro základní operace s uživateli psát jakýkoli kód. Přihlašování nebo registrování uživatelů můžete zprovoznit pouze pomocí drag-dropu několika prvků. Přidat do stránky rámeček pro přihlašování uživatelů je nyní stejně jednoduché jako vložit do stránky třeba Label
.
Framework .NET 2.0 je dodáván se dvěma základními poskytovateli – AccessMembershipProvider
a SqlMembershipProvider
. Nyní bych řekl něco málo ke každému z nich. Základní rozdíl je myslím jasný. Prvek SqlMembershipProvider
používá jako datový zdroj MS SQL databázi, zatímco AccessMembershipProvider
uchovává uživatele v Accessu.
Pro větší názornost jsem připravil zdrojové kódy ukázek, které si můžete stáhnout a vyzkoušet.
AccessMembershipProvider
Aby začal tento provider „pracovat“ stačí zpřístupnit formulářovou autentizaci:
<authentication mode=”Forms” />
Spokojíte-li se s defaultním nastavením, tento provider se postará prakticky o všechno. Vytvoří si dokonce i potřebné databázové objekty. Na vás zůstává pouze „natáhnout“ do stránky ovládací prvky pracující s uživatelskými účty. Základní chování však nemusí vždy vyhovovat, proto máme možnost modifikovat chování provideru podle našich představ:
<membership defaultProvider=“AccessProvider“ userIsOnlineTimeWindow=“15″>
<providers>
<clear />
<add
name=“AccessProvider“
type=“System.Web.Security.AccessMembershipProvider“
connectionStringName=“MyAccessConnString“
applicationName=“firstApp“
enablePasswordRetrieval=“false“
enablePasswordReset=“true“
requiresQuestionAndAnswer=“true“
requiresUniqueEmail=“true“
passwordFormat=“Hashed“ />
</providers>
</membership>
Pomocí atributu name
nastavíte název providera. Tento název použijete na prvním řádku ukázky:
<membership defaultProvider=“AccessProvider“ . . . >
Atribut type
říká aplikaci, kde má hledat třídu providera. V .NET Frameworku můžete najít (zatím) dva, System.Web.Security.AccessMembershipProvider
a System.Web.Security.SqlMembershipProvider
. Nic vám však nebrání napsat svůj vlastní provider. Mně například chybí provider pro XML soubory.
Atribut ConnectionStringName
pouze ukazuje na připojovací řetězec k databázi, uložený v sekci connectionStrings
v souboru web.config:
<connectionStrings>
<add name=“MyAccessConnString“ connectionString=“. . .“ />
</connectionStrings>
Atribut ApplicationName
se hodí, hostujete-li více aplikací na jednom webserveru. Tímto atributem zajistíte odlišení uživatelů příslušících k jednotlivým aplikacím.
Nastavíte-li enablePasswordRetrieval
na true
, bude mít zapomětlivý uživatel možnost nechat si poslat ztracené heslo. Je-li však atribut passwordFormat
nastaven na Hashed
, nebudou uživatelé ze zřejmých důvodů schopni obdržet heslo z databáze.
Podobné je to s enablePasswordReset
. Tato vlastnost se ovšem nijak nekryje s vlastností passwordFormat
. Atribut enablePasswordReset
jednoduše umožňuje (respektive znemožňuje) uživatelům, aby si nechali na e-mail poslat nové, náhodně generované heslo. Můj názor je ten, že je rozumnější nastavit enablePasswordRetrieval
na false
a enablePasswordReset
na true
. Chcete-li hesla hešovat, myslím, že je toto jediná rozumná varianta.
Atribut RequiresQuestionAndAnswer
řeší oblast bezpečnostních otázek, požaduje-li uživatel poslání hesla na e-mail, respektive jeho resetování.
Je-li requiresUniqueEmail
nastaveno na true
, bude aplikace požadovat, aby se v databázi nevyskytli dva uživatelé se stejným e-mailem.
Atribut PasswordFormat
může nabývat tří hodnot, Clear
, Encrypted
a Hashed
. Všechny tři způsoby uchování hesel jsem popsal v článku Salted hash – další krok ke zvýšení bezpečnosti. Pro úplnost doplním, že možnost hashed
ve skutečnosti používá hash se saltem.
SqlMembershipProvider
S poskytovatelem pro MS SQL vám v činnosti přibude ještě jeden krok navíc, nicméně u větších aplikací se s Accessem těžko spokojíme. Na rozdíl od providera pro Access, SqlMembershipProvider
za vás potřebné databázové objekty nevytvoří. Tato operace je na vás. Tolik práce to zase ale není, s frameworkem je dodáván nástroj (aspnet_regsql), který stačí spustit z příkazového řádku, a ten vám s tím pomůže. Pro úplnost ještě doplním ukázku ze souboru web.config pro MS SQL providera:
<membership defaultProvider=“SqlProvider“ userIsOnlineTimeWindow=“15″>
<providers>
<clear />
<add
name=“SqlProvider“
type=“System.Web.Security.SqlMembershipProvider“
connectionStringName=“sqlConnString“ applicationName=“firstApp“
enablePasswordRetrieval=“false“
enablePasswordReset=“true“
requiresQuestionAndAnswer=“true“
requiresUniqueEmail=“true“
passwordFormat=“Hashed“ />
</providers>
</membership>
Login Controls
Když už aplikace ví, jak si přejeme, aby s uživatelskými účty pracovala, můžeme začít tvořit stránky. Ke správě uživatelů slouží takzvané Login Controls
. Nyní si postupně ukážeme ty nejzajímavější.
CreateUserWizard
Abychom vůbec měli v aplikaci nějaké uživatele, musíme je nejdříve vytvořit. K tomu nám velmi dobře poslouží, jak už sám název napovídá, CreateUserWizard
. Tento prvek (stejně jako některé další) se vykreslí přesně podle nastavení, která jsme zanechali v souboru web.config v sekci <membership />
. Pokud tedy v našem příkladu máme nastaveno requiresQuestionAndAnswer
na true
, zobrazí tento prvek textová pole pro bezpečnostní otázku a odpověď. Stejným způsobem se chovají i další prvky, ke kterým se ještě dostaneme.
<asp:CreateUserWizard ID=“createUser“ runat=“server“ />
Tento zápis přidá do stránky prvek, který se postará o registrování nových uživatelů. Nemusíte psát žádné obslužné metody událostí, postará se opravdu úplně o všechno.
Možná by ale bylo dobré trochu poupravit vzhled a asi také přeložit popisky (máme to přeci jen o něco složitější než Angličané). O vzhled se můžete postarat způsobem, na jaký jste v .NETu zvyklí. Ostatně o popisky také. Máte-li například Visual WebDeveloper, najdete si vlastnosti řešící tuto problematiku celkem snadno, v opačném případě vás odkážu na dokumentaci, kde je vše vyčerpávajícím způsobem popsáno. Nicméně, pokud vám předvedu prvních pár vlastností, které jsou nositeli textů v popiscích, věřím, že ostatní už hravě odhadnete, takže: UserNameLabelText
, PasswordLabelText
, ConfirmPasswordLabelText
…
Zmíním ovšem ještě jinou vlastnost, která se mi zdá užitečná. Bude-li AutoGeneratePassword
rovno true
, neobjeví se v boxu položky Password a Confirm Password a heslo bude náhodně generováno a odesláno na uživatelův e-mail. K tomu budeme ale muset ještě něco málo přidat do prvku CreateUserWizard
:
<asp:CreateUserWizard ID=“CreateUser“ runat=“server“ >
<MailDefinition BodyFileName=“~/userregmail.txt“
From=“vas @ server.cz“
Subject=“Potvrzeni registrace“ />
</asp:CreateUserWizard>
Ve vlastnosti BodyFileName
definujeme umístění textového souboru s tělem e-mailu. Uvnitř tohoto souboru můžete používat výrazy typu <% UserName %>
či <% Password %>
, abyste byli schopni uživateli sdělit jeho nacionále. Tento scénář se také může hodit, abyste měli jistotu, že e-mail, který uživatel zadal, je platný. Konfigurace odesílání e-mailu podléhá nastavení sekce smtpMail
v souboru web.config.
Login Control
Nyní bychom měli vytvořit rozhraní pro logování již existujících uživatelů. O to se postará prvek Login
. Podobně jako CreateUserWizard
, ani Login
nepotřebuje ke své činnosti nic víc, než vložit do stránky:
<asp:Login ID=“Login“ runat=“server“ />
Tento zápis bude mít za následek zhruba tento výstup:
Vzhled opět nevalný, ale s tím si teď lámat hlavu nebudeme. Asi by ale opět bylo vhodné změnit UserNameLabelText
a PasswordLabelText
na české hodnoty. Tady však chci, kromě již zmiňovaných UserNameLabelText
a PasswordLabelText
, poukázat na existenci několika dalších vlastností:
CreateUserText
aCreateUserUrl
– text a odkaz na stránku, která zařídí registraci nového uživatele.DisplayRememberMe
– určuje, má-li se zobrazitCheckBox
„remember me“.RememberMeSet
– defaultní stavCheckBoxu
„remember me“.RememberMeText
– popisek uChceckBoxu
„remember me“.FailureText
– zpráva, která se zobrazí po neúspěšném pokusu o ověření identity uživatele.PasswordRecoveryText
aPasswordRecoveryUrl
– odkaz, který se postará o uživatele, ztratí-li své heslo. Za tímto odkazem by se měl skrývat prvekPasswordRecovery
.VisibleWhenLoggedIn
– umožňuje skrýt box po přihlášení uživatele.
PasswordRecovery Control
Tento prvek umožní uživatelům získat zpět, respektive generovat nové heslo. Základní chování opět závisí na nastavení providera v souboru web.config. Máte-li nastaveno hashování hesel, těžko mu asi aplikace pošle heslo, ale spíše vygeneruje nové. Hesla jsou odesílána na uživatelův e-mail a stejně jako u prvku CreateUserWizard
musíme nejdřív definovat vlastnosti tohoto e-mailu. Rovnou uvedu ukázku, po zkušenostech s předchozími prvky bude vše jasné:
<asp:PasswordRecovery ID=“PasswordRecovery“ runat=“server“>
<MailDefinition BodyFileName=“~/passwordremind.txt“
From=“vas@server.cz“
Subject=“Ztracene heslo“ />
</asp:PasswordRecovery>
Po vložení platného uživatelského jména se zobrazí bezpečností otázka, kterou zadal uživatel při registraci:
ChangePassword Control
Co se týče funkce tohoto prvku, není zde, myslím, co vysvětlovat. Před samotnou změnou hesla se aplikace klasicky „zeptá“ na heslo aktuální, poté dvakrát na nové. Stejně jako již zmiňované prvky PasswordRecovery
a CreateUserWizard
, obsahuje i tento vlastnost MailDefinition
:
<asp:ChangePassword ID=“ChangePass“ runat=“server“>
<MailDefinition BodyFileName=“~/changepass.txt“
From=“vas@server.cz“
Subject=“Zmenene heslo“ />
</asp:ChangePassword>
LoginStatus a LoginName
Tyto dva prvky se většinou používají společně. Společně také bývají popisovány a ani já tento trend nenaruším. Prvek LoginName
zobrazuje jméno přihlášeného uživatele. Není-li nikdo přihlášen, nezobrazí se nic. Prvek LoginStatus
zobrazuje vždy jeden ze dvou odkazů – buď Login (je-li uživatel anonymní) nebo Logout (byl-li uživatel již přihlášen). Použijete-li tyto dva prvky společně, může se vám dostat například tohoto výstupu:
Po klepnutí na Login se stránka přesměruje na URL definované v souboru web.config, kde by nejspíš mohl čekat prvek Login
, který jsme si už probrali:
<authentication mode=“Forms“>
<forms loginUrl=“Login.aspx“>
. . .
</forms>
</ authentication>
Prvek LoginStatus
předá přihlašovací stránce URL, ze kterého byla volána, takže po úspěšném přihlášení se uživatel opět vrátím tam, kde před tím skončil, avšak již přihlášený:
Je-li tedy uživatel již přihlášen, LoginStatus
v našem případě zobrazí odkaz s textem „(odhlásit)“, LoginName
nám ukazuje jméno přihlášeného. Kód zajišťující tuto funkcionalitu vypadá zhruba takto:
<asp:LoginName ID=“name“ runat=“server“
FormatString=“Přihlášený uživatel: {0}“ />
<asp:LoginStatus ID=“status“ runat=“server“
LogoutText=“(odhlásit)“ LoginText=“Login“ />
LoginView Control
Když už jsme prošli správu uživatelů, můžeme přejít k zobrazování obsahu samotným uživatelům. Abych řekl pravdu, tento prvek mě tak trochu zklamal. Prvek LoginView
zobrazuje různý obsah závisející na rolích jednotlivých uživatelů, respektive na stavu uživatele – přihlášený nebo anonymní:
<asp:LoginView ID=“LoginView“ runat=“server“>
<LoggedInTemplate>
Obsah pro přihlášené uživatele….
</LoggedInTemplate>
<AnonymousTemplate>
Chcete-li vidět to co vidí přihlášení, přihlaste se…
</AnonymousTemplate>
</asp:LoginView>
Až do tohoto bodu s tímto prvkem žádný problém nemám. Pokračujme však dále. Již jsem zmínil, že tento prvek podporuje i zobrazení obsahu podle jednotlivých rolí. To je také pěkná myšlenka. Aplikace tedy může vypadat například takto:
<asp:LoginView ID=“LoginView“ runat=“server“>
<RoleGroups>
<asp:RoleGroup Roles=“Admini“>
<ContentTemplate>
Obsah pro administrátory…
</ContentTemplate>
</asp:RoleGroup>
<asp:RoleGroup Roles=“Management“>
<ContentTemplate>
Obsah pro management společnosti…
</ContentTemplate>
</asp:RoleGroup>
</RoleGroups>
<LoggedInTemplate>
Ahoj <asp:LoginName ID=“LogName“ Runat=“server“ />
</LoggedInTemplate>
<AnonymousTemplate>
Prosím přihlašte se. . .
</AnonymousTemplate>
</asp:LoginView>
Tady je však zakopán pes. Každý uživatel může vidět pouze obsah své role. Management tedy nemůže vidět to, co vidí administrátoři (chápu), ale nemůže vidět ani obsah LoggedInTemplate
nebo AnonymousTemplate
. Administrátorům bychom taky asi nemuseli skrývat obsah například LoggedInTemplate
. Zkrátka si myslím, že existují role, které by měly mít přístup do většího počtu šablon, než jen do té své. Přiznám se, že jsem ještě toto téma nezkoumal do největších podrobností, ale myslím, že pro univerzálnější použití bude vhodné poupravit tento prvek, aby přijímal jakýsi hierarchický model rolí.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Mohlo by vás také zajímat
-
AI a internetové podvody
29. října 2024 -
Zvýšení výkonu WiFi signálu: Jak a proč používat WiFi zesilovače
28. června 2023
Nejnovější
-
Výkonný a kompaktní: ASOME Max Studio s výjimečným poměrem cena/výkon
11. listopadu 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
OpenAI představilo novou funkci ChatGPT Search
6. listopadu 2024