Form Auth

W tym wpisie opiszę jak w prosty sposób można stworzyć uwierzytelnienie w ASP.NET. Nie będą nam potrzebne żadne domyślne kontrolki logujące. Nie będzie nam potrzebna żadna baza danych. Nie będą nam potrzebne nawet klasy pomocnicze jak MembershipProvider czy inne providery.

Tak swoją drogą domyślny MemebershipProvider pozwala nam na łatwą konstrukcję serwisu z użytkownikami. Jest on wykorzystany w niektórych szablonach projektów ASP.NET. Dziedzicząc po nim możemy stworzyć swój własny system użytkowników według wzoru tejże klasy. Jednak nie o tym w dzisiejszym wpisie.

Chcę skoncentrować się na samym końcu tego mechanizmu, czyli na samym logowaniu .Na momencie, w którym dane użytkownika zostają zapisane do sesji oraz trafiają do ciasteczek i o dziwo nie jest to takie trudne wykorzystując klasę FormAuthentication.

Dzisiaj pokażę wam jak napisać najprostsze uwierzytelnienie, jakie można stworzyć w ASP.NET. Do prostego uwierzytelniania wystarczy nam klasa statyczna FormAuthentication.

Klasa ta w metodzie statycznej “RedirectFromLoginPage“ stworzy odpowiedni “ticket” dla użytkownika. Interesującą sprawą jest fakt, że to my podajemy tego użytkownika w kodzie co oznacza ,że każdy użytkownik na tym poziomie może być uwierzytelniony. Dlatego w kodzie, zastosuję proste wyrażenie “if user==”tomek” . Ogólnie umieszczanie haseł w kodzie to kiepski pomysł. Jeśli popatrzysz na inne metody klasy FormAuthentication zauważysz , że jest ona dostosowana do scenariusza, w którym użytkownicy i hasła są przetrzymywane i haszowanie w web.configu. Jednak nie o tym dziś mowa. Aby usunąć użytkownika z sesji, jaki i z ciasteczek użyjemy metody “SignOut” z klasy FormAuthentication.

Do tej aplikacji będą potrzebne dwie strony internetowe ": LogOn.aspx i Index.aspx”. Do poprawnego działania uwierzytelnienia w postaci formularza internetowego musimy też zmienić plik “web.config. Spokojnie wszystko opiszę krok po kroku.

Tworzenie projektu

Na początku stwórzmy pusty projekt ASP.NET. Aby to zrobić wybierz template “ASP.NET Empty Web Application”.

uwierzytelniania ASP.NET_01

Projekt powinien wyglądać tak. Jeśli tak nie jest oznacza to ,że wybrałeś zły projekt.

uwierzytelniania ASP.NET_02

Edycja pliku Web.config

1. Kliknij dwa razy na plik “Web.config”. Na razie wygląda on tak. Jeśli masz dużo więcej kodu w Web.config oznacza to ,że korzystasz ze starszej wersji ASP.NET ,ale nie martw się nie jest to żadna blokada dla naszego zadania.

2. Wewnątrz elementu “system.web” dodaje element “authentication” i ustaw jego właściwość mode na “Forms”. W ten sposób mówisz aplikacji ASP.NET ,że będziesz korzystał z uwierzytelnienia przy pomocy formularzy

uwierzytelniania ASP.NET_08

Jeśli jesteś ciekaw, jakie są inne opcje uwierzytelniania w ASP.NET przyjrzyj się menu pomocniczemu w czasie uzupełniania kodu dla właściwości “mode”. Jak widać są do wyboru opcje:

  • · Windows – uwierzytelnienie na bazie użytkownika Windows.
  • · Form - tradycyjny i najbardziej znany rodzaj uwierzytelnienia – formularz ze strony internetowej
  • · Passport – stary pomysł Microsoftu jeszcze z NET 1.1 polegający na posiadaniu uniwersalnego ciasteczka, które miał działać wielu usługach i stronach równocześnie. Do implementacji tej usługi jest wymagana biblioteka NET Passport SDK . Nikt z tego nie korzysta.
  • · None – domyślne ustawienie.

Mając już ustawioną opcję mode na Forms. Możemy przejść do następnego punktu.

<?xml version="1.0"?> 
<configuration> 
   <system.web> 
        <compilation debug="true" targetFramework="4.0" /> 
        <authentication mode="Forms"> </authentication> 
    </system.web> 
</configuration>

3. Wewnątrz elementu “authentication” dodaj element “forms” i uzupełnij go, tak jak jest to pokazane poniżej. W tym punkcie określamy nazwę formularza, jak i jego stronę logującą oraz stronę domyślną, na którą użytkownik zostanie przekierowany po logowaniu.

<?xml version="1.0"?> 
<configuration> 
    <system.web> 
        <compilation debug="true" targetFramework="4.0" /> 
         <authentication mode="Forms"> <forms loginUrl="LogOn.aspx" name=".ASPXFORMSAUTH" defaultUrl="Index.aspx" /> 
         </authentication> 
     </system.web> 
</configuration>

4. Tyle, jeśli chodzi o ustalanie opcji formularza i typu uwierzytelnienia. Teraz aby wykazać ,że formularz logujący działa zablokujemy wszystkim anonimowym użytkownikom dostęp do strony domyślnej.

Na początek dodaj element “authorization” do elementu “system.web”.

<?xml version="1.0"?> 
<configuration> 
   <system.web> 
      <compilation debug="true" targetFramework="4.0" /> 
      <authentication mode="Forms"> <forms loginUrl="LogOn.aspx" name=".ASPXFORMSAUTH" defaultUrl="Index.aspx" /> 
      </authentication> 
      <authorization> </authorization> 
   </system.web> 
</configuration>

5. Potem dopisz pod elementem “authorization” element “deny” i ustaw na go na “user=”?”.

Ten fragment tekstu w web.configu sprawi ,że tylko zalogowani użytkownicy będą mieli dostęp do zasobów strony. Anonimowi użytkownicy będą mogli skorzystać tylko z formularza logującego.

<?xml version="1.0"?> <
<configuration> 
    <system.web> 
         <compilation debug="true" targetFramework="4.0" /> 
         <authentication mode="Forms"> <forms loginUrl="LogOn.aspx" name=".ASPXFORMSAUTH" defaultUrl="Index.aspx" /> 
         </authentication> 
         <authorization> 
                <deny users="?" /> 
         </authorization> 
    </system.web> 
</configuration>

Na tym kończy się edycja pliku web.config.

Stworzenie dwóch stron aspx

Aby dodać stronę ASP.NET do projektu kliknij prawym na ikonkę projektu

uwierzytelniania ASP.NET_03

 

Z okna dialogowego wybierz element “Web Forms” i nazwij go “LogOn.aspx” dla konsystencji z danymi zawartymi w pliku web.config.

uwierzytelniania ASP.NET_04

Analogicznie stwórz stronę “Index.aspx”.

uwierzytelniania ASP.NET_05

Moja strona “LogOn.aspx” wygląda tak.

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Prosta uwierzytelnienie ASP.NET - Statyczna klasa FormsAuthentication</title>
</head>
<body>
    <h1>Login Page</h1>
    <form id="form1" runat="server">
    Login_ :
    <asp:TextBox ID="txtLogin" runat="server" /><br />
    <br />
    Hasło_ :
    <asp:TextBox ID="txtPassword" runat="server" /><br />
    <br />
    <asp:CheckBox ID="chkPersist" runat="server" Text="Zapamiętaj mnie w ciasteczkach" /><br />
    <br />
    <asp:Button ID="btnLog" runat="server" Text="Zaloguj" OnClick="btnLog_Click" />
    </form>
</body>
</html>

Jak widać strona zawiera w sobie dwa textboxy oraz jeden checkbox i przycisk. Textboxy naturalnie służą do wpisywania danych identyfikacyjnych jak login i hasło. Checkbox określa czy informacje o użytkowniku mają też być zapisane w ciasteczkach, w przeglądarce. Oznacza to, że nawet po zamknięciu przeglądarki wciąż będziesz uwierzytelniony w aplikacji, ponieważ przeglądarka ma zapisane twoje dane. Oczywiście są zaszyfrowane. Przycisk zatwierdza operacje logowania.

uwierzytelniania ASP.NET_07

Moja prymitywna strona logująca wygląda tak.

Przejdźmy teraz do kodu pobocznego. Aby to zrobić rozszerz stronę ASPX i wybierz plik “LogOn.aspx.cs”.

kod poboczny

Mój kod poboczny wygląda tak.

using System;
using System.Web.Security;

namespace UwierzytelnienieForm
{
    public partial class LogOn : System.Web.UI.Page {
        protected void btnLog_Click(object sender, EventArgs e)
        {
            if ((txtLogin.Text == "Cezary") && (txtPassword.Text == "12345"))
            {
                FormsAuthentication.RedirectFromLoginPage
                    (txtLogin.Text,chkPersist.Checked);
            }
            else 
            {
                Response.Write("Błędne dane. Spróbuj jeszcze raz");
            }
        }
    }
}

Nie ma tutaj niczego skomplikowanego. W czasie naciśnięcia przycisku sprawdzam czy dane podane przez użytkownika zgadzają się z moim. Jeśli tak jest wywołuje metodę “RedirectFromLoginPage” przerzuci ona użytkownika do domyślnej strony i zapisze go w sesji. Do tej metody trzeba podać nazwę użytkownika oraz wartość logiczną określającą czy chcemy przechowywać te informacje też w ciasteczkach w przeglądarce.

Nie ma to, jak prosty warunek “if” w innych porządnych aplikacjach ten proces przechodzi przez wiele warstw abstrakcji tutaj ich nie ma.

Prawie zapomniałbym - w stronie brakuje jeszcze jednej rzeczy. Jest to kropkowanie treści pola tekstowego, gdy piszemy hasło. Aby to zrobić wystarczy do TextBox-a dopisać właściwość“TextMode=”Password”

 <asp:Textbox id="txtPassword" runat= "server" TextMode="Password" />

To wszystko, jeśli chodzi o stronę logującą.

Wylogowywanie

Na stronie“index.aspx” musimy udowodnić ,że użytkownik jest zalogowany. Strona ta jest jeszcze mniej rozbudowana niż strona logująca. Zawiera tylko przycisk wylogowujący oraz prosty “label”, który zostanie uzupełniony nazwą użytkownika.

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:Label ID="lblUserInfo" runat="server" Text="Label" /><br />
    <br />
    <asp:Button ID="btnLogOut" runat="server" Text="Wyloguj" OnClick="btnLogOut_Click" />
    </form>
</body>
</html>

Wygląd strony po kompilacji.

image

W kodzie pobocznym w zdarzeniu“Page_Load” możemy pobrać informacje o użytkowniku z właściwości Contex.User.Identity.Name. Potwierdza to , że jesteśmy zalogowani. Zresztą, gdybyśmy nie byli, to byśmy nie weszli na tę stronę.

Dla zdarzenia kliknięcia “btn_LogOut” wywołujemy metodę“SignOut()” z klasy FormAuthentication. Metoda ta usunie użytkownika z sesji jak i skasuje jego ciasteczka, jeśli one istnieją. Pod koniec trzeba przenieść użytkownika na inną stronę, ponieważ sama metoda “SignOut()” tego nie robi.

using System;
using System.Web.Security;

namespace UwierzytelnienieForm
{
    public partial class Index : System.Web.UI.Page {
        protected void Page_Load(object sender, EventArgs e)
        {
            lblUserInfo.Text = Context.User.Identity.Name;
        }

        protected void btnLogOut_Click(object sender, EventArgs e)
        {
            FormsAuthentication.SignOut();
            Response.Redirect("LogOn.aspx");
        }
    }
}

To wszystko. Być może następnym razem omówię jak z poziomu kodu stworzyć dynamicznie role użytkowników. Pokazując jak te mechanizmy działają bez tej całej warstwy abstrakcji.