BETA
Aby się zalogować, najpiew wybierz portal.
Aby się zarejestrować, najpiew wybierz portal.
Podaj słowa kluczowe
Słowa kluczowe muszą mieć co najmniej 3 sąsiadujące znaki alfanumeryczne
Pole zawiera niedozwolone znaki

Baza wiedzy











Parę słów o web.config

14-09-2004 12:20 | Greegory

Wstęp

Projekt ten będzie się składał z dwóch etapów. Pierwszy etap to utworzenie odpowiedniej bazy i nadanie uprawnień dla użytkownika strony. Drugi to stworzenie aplikacji na stronie.
W skład tego etapu wchodzi stworzenie metod szyfrujących hasło, utworzenie sesji oraz dostęp do bazy danych przez plik web.config.

Kto powinien czytać dalej?

Każdy, kto chce napisać aplikację prędzej czy później spotka się z problemem ograniczenia dostępu. Dla tych początkujących programistów, którzy nie chcą przeczesywać Internetu
(i nadwyrężać i tak już zmęczonych oczu), w poszukiwaniu rozwiązań tego problemu napisałem ten artykuł.

Z dostępnych sposobów uwierzytelniania wybrałem „Forms authentication”. Nie jest on najbezpieczniejszy, ale na początek powinien wszystkich zadowolić. Hasła i loginy będziemy przechowywać w bazie danych i wyciągać je za pomocą procedur składowanych. Z tym, że hasła do bazy wstawiamy już w postaci zahaszowanej.

Utworzenie potrzebnej bazy danych

Na początek musimy stworzyć bazę danych dla potrzeb projektu, będzie to jedna tabela z dwoma polami login i hasło oraz procedurą składowaną. Poniżej przedstawiam kod, który najlepiej wkleić do Query Analyzer.

Tworzymy najpierw bazę niezbędną do przechowywania haseł i loginów. Rekord na hasła jest dość znaczny. Wynika to z faktu, że nie przechowujemy hasła, lecz jego zaszyfrowany odpowiednik.

CREATE DATABASE code
GO
USE code
GO
/* utworzenie tabeli z uzytkownikami */
CREATE TABLE students
(
     st_login VARCHAR(30) NOT NULL PRIMARY KEY,
     st_password VARCHAR(47) NOT NULL
)
GO

Kiedy już mamy stworzoną bazę musimy dodać procedurę, służące do sprawdzania czy użytkownik wpisał prawidłowe dane.

CREATE PROCEDURE StudentLogin
(
     @login VARCHAR(30),
     @password VARCHAR(47),
     @isCorect BIT OUTPUT
)
AS
     IF EXISTS
     (
          SELECT st_login
          FROM students
          WHERE st_login = @login AND st_password = @password
     )
          SET @isCorect = 1
     ELSE
          SET @isCorect = 0
GO

Teraz pozostało nam jeszcze wprowadzenie odpowiednich danych abyśmy mogli przetestować, ze strony, czy nasza baza działa.

INSERT INTO students
VALUES (´login´, ´5F-4D-CC-3B-5A-A7-65-D6-1D-83-27-DE-B8-82-CF-99´)
GO

Ten jakże dziwny ciąg cyferek to potraktowane algorytmem MD5 hasło password. Ponieważ musimy mieć wpisane jakieś hasło do bazy, a ta jest przeznaczona już na zaszyfrowane dane. Dlatego umieściłem hasło potraktowane metodą Hash (opisaną w dalszej części artykułu). Na tym etapie należy tylko przepisać powyższego inserta, a wszystko zrobi się jasne już za parę minut.

Teraz pozostaje jeszcze przydzielić użytkownikowi nazwa_komputera\ASPNET dostęp do nowo utworzonej bazy code, a następnie możliwość wykonywania procedury wyżej utworzonej. W tym celu otwieramy Enterprise Manager i rozwijamy drzewo, aż do momentu spotkania naszej bazy code. Po czym zaznaczamy w lewej kolumnie user, gdy to wykonamy pojawią się nam użytkownicy bazy. Do listy użytkowników należy dodać wyżej wymienionego. Aby to zrobić wykonujemy następujące kroki: naciskamy prawym klawiszem myszy na kolumnę po prawej stronie i wybieramy z menu podręcznego new database user… Po tym kroku wybieramy naszego użytkownika ASPNET. Wygląda to miej więcej tak jak na poniższym zdjęciu.

Teraz ostatni etap związany z bazą danych. Przydzielenie możliwości wykonywania procedury składowanej użytkownikowi ASPNET. W tym celu wybieramy z prawej kolumny w drzewie Storage Procedure. Po prawej stronie szukamy naszej procedury (powinna być na samym dole). Naciskamy na niej prawym klawiszem myszy i wybieramy z menu podręcznego pole Właściwości. Pojawia się okno Storage Procedure Properties, wybieramy Permissions i zaznaczamy przy nazwa_komputera\ASPNET prawo do wykonywania EXEC. Zatwierdzamy naciskając OK.

Utworzenie aplikacji webowej ASP.NET

Teraz, kiedy już mamy niezbędną bazę danych możemy przejść do utworzenia właściwej aplikacji. Po pierwsze należy stworzyć nowy projekt w VS.Net. Typ projektu to ASP.NET Web Application a język, jakiego użyjemy to C#. Następnie należy podać jeszcze tylko nazwę, u mnie to wygląda tak http://localhost/Sesja.. Na koniec oczywiście naciskamy OK.

Teraz już z górki. Ponieważ jest to artykuł dla tych, którzy już co nieco orientują się w technologii .NET, więc nie będę szczegółowo opisywał przeciągania etykiet, przycisków oraz pól tekstowych.

Poniżej przedstawię jak powinna wyglądać strona do logowania się i jak nazwać odpowiednie pola i przyciski. Strzałkami wskazują jak nazwać odpowiednie obiekty.

Mając stronę służąca do logowania musimy mieć jeszcze stronę z naszymi cennymi danymi, które należy chronić w tym celu szukamy, w okienku Solution Explorer, słowa Sesja (tak jak nazywa się nasz projekt). Naciskamy prawym guzikiem myszy na Sesja i wybieramy z menu podręcznego Add, a następnie Add Web Form… Po naszej akcji nastąpi reakcja w postaci okienka. Naciskamy OK i gotowe. Teraz tylko dodajemy do nowej strony etykietę o nazwie labInfo no i tyle wystarczy. Wyglądać to będzie jakoś tak.

Kolejny etap to odpowiednie zaprojektowanie pliku web.config. Aby tego dokonać należy zastosować starą sprawdzoną metodę niszczymy wszystko, co tam jest i wklejamy poniższy tekst.

<configuration>
     
     <!-- Ustawienie domyslnej strony logowania. Wszystkie pozostale
     strony beda przez nia zabezpieczone.
     -->
     <system.web>
          <authentication mode="Forms">
               <forms name=".ASPXAUTH" loginUrl="WebForm1.aspx" />
          </authentication>
<!-- Zezwolenie na debagowanie -->
<compilation defaultLanguage="c#" debug="true" />
     </system.web>
     
     <!-- Ustawienie polaczenia z baza danych pierwszy parametr to nazwa polaczenia
     nastepnie wazny to nazwa jednostki, tu domyslnie localhost. Domyslna serwer
     bazodanowy oraz jako katalog nazwa naszej bazy danych tu code
     -->
     <appSettings>
          <add key="conCode" value="workstation id=localhost;
               packet size=4096;
               integrated security=SSPI;
               data source=localhost;
               persist security info=False;
               initial catalog = code"
          />
          <add key="sqlConnection1.ConnectionString" value="" />
     </appSettings>
     <!-- Tu wypisujemy strony ktore chcemy by byly zabezpieczone -->
     <location path="WebForm2.aspx">
          <system.web>
               <authorization>
                    <deny users="?" />
               </authorization>
          </system.web>
     </location>
</configuration>

Kolejny kamień milowy za nami. Teraz przechodzimy to pisania aplikacji właściwej. Wracamy do WebForm1.aspx. Otwieramy toolbox, wybieramy zakładkę Data i przeciągamy na webformsa sqlConnection. Tworzy się nam obiekt typu sqlConnection o nazwie sqlConnection1. Zaznaczamy go i naciskamy F4 (przechodzimy do właściwości połączenia). Po przejściu do właściwości połączenia, ustawiamy, aby połączenia było szukane z w pliku web.config. Aby to zrealizować w Properties rozwijamy Dynamic Properties i w polu ConnectionString wpisujemy conCode (tak nazwaliśmy nasze połączenie w pliku web.config). Po wciśnięciu klawisza ENTER powinno się pojawić, w polu poniżej w właściwości Data, wpisane wcześniej połączenie z bazą danych.

No to teraz odrobina kodu. Pierwszy etap to dołączenie odpowiednich przestrzeni nazw. Odpowiadających kolejno za połączenie z bazą danych, metody szyfrujące oraz metody pozwalające na używanie znaków nie tylko 8- bitowych.

using System.Data.SqlClient;
using System.Web.Security;
using System.Security.Cryptography;
using System.Text;

Na początku zajmiemy się szyfrowaniem hasła. Proces szyfrowania powinien odbyć się już po stronie klienta. W tym celu utworzyłem procedurę Hash. Hash pobiera hasło i zwraca je w postaci stringu, przygotowane do sprawdzenia już w bazie użytkowników.

/// <summary>
/// Procedura umozliwia szyfrowanie hasla.
/// </summary>
/// <param name="password">Dostajemy na wejsciu haslo w postaci nie
/// zaszyfrowanej, jako string</param>
/// <returns>Zwraca nam 47 znakowy unikalny ciag reprezentujacy nasze
/// haslo.</returns>
private string Hash(string password)
{
     // tworzymy obiekt udostepniajacy metode odpowiedzialna za kodowanie
     // naszego hasla.
     MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
     // tworzymy tablice zmiennych typu byte gdyz takiej postaci wymaga
     // metoda hash- ujaca
     Byte[] hashedDataBytes;
     // obiekt ten udostepnia metody pozwalajace na zapisanie znakow z
     // poza
     // standardowego 8- bitowego zakresu znakowego. Dzieki uzyciu
     // procedury udostepnianej przez ten obiekt nie gubimy tych znakow.
     UTF8Encoding encoder = new UTF8Encoding();
     // 1. bierzemy nasze haslo i zmieniamy ja do postaci tablicy byty
     //    nie gubiac przy tym niestandardowych znakow
     // 2. kodujemy haslo za pomoca jednokierunkowej funkcji skrotu
     //       i wpisujemy je do tablicy
     hashedDataBytes = md5Hasher.ComputeHash(encoder.GetBytes(password));
     // zamieniamy do naszej ulubionej postaci string i zwracamy
     return BitConverter.ToString(hashedDataBytes);
}

Zostało nam jeszcze utworzenie metody łączącej naszą stronę z bazą danych.

/// <summary>
/// Metoda jest odpowiedzialna za komunikacje z baza danych.
/// Pobiera login i haslo. Haslo jest szyfrowanie za pomoca
/// metody Hash, po czym wywolywana jest procedura na serwerze
/// bazodanowym. Procedura zwraca true jesli zalogowanie bylo
/// poprawne.
/// </summary>
/// <param name="login">Login uzytkownika.</param>
/// <param name="password">Haslo uzytkownika w postaci nie zaszyf
/// rowanej.</param>
/// <returns>Zwraca prawde jesli mozemy sie zalogowac.</returns>
private bool StudentLogin(string login, string password)
{
     // przypisanie polaczenia z baza danych na potrzeby metody
     SqlConnection objConnection = sqlConnection1;
SqlCommand objCommand =
new SqlCommand("StudentLogin", objConnection);
     // ustalenie typu polaczenia jako procedura skladowana
     objCommand.CommandType = CommandType.StoredProcedure;
     // wpisanie pierwszego parametru wejsciowego
     SqlParameter parameterIn1 =
new SqlParameter("@login",SqlDbType.VarChar, 30);
parameterIn1.Value = login;
     objCommand.Parameters.Add(parameterIn1);
     // wpisanie drugiego parametru wejsciowego
     SqlParameter parameterIn2 =
new SqlParameter("@password",SqlDbType.VarChar, 47);
     parameterIn2.Value = (this.Hash(password)).ToString();
     objCommand.Parameters.Add(parameterIn2);
     // ustalenie parametru wyjsciowego
     SqlParameter parameterOut1 =
new SqlParameter("@isCorect", SqlDbType.Bit, 1);
     parameterOut1.Direction = ParameterDirection.Output;
     objCommand.Parameters.Add(parameterOut1);
     // proba otwarcia i wyegzekwowania polaczenia z baza
     try
     {
          objConnection.Open();
          objCommand.ExecuteNonQuery();
     }
     catch (Exception)
     {
labError.Text = "Nieudane połączenie z bazą danych!";
     }
     finally
     {
          if (objConnection.State == ConnectionState.Open)
          {
               objConnection.Close();
          }
     }
     // konwersja parametru
     return Convert.ToBoolean(parameterOut1.Value);
}

Teraz została nam tylko formalność przypisanie zdarzeń do naszego przycisku Submit. W tym celu przechodzimy na strony WebForm1.aspx i naciskamy dwa razy na przycisk. Powinniśmy znaleźć się w kodzie odpowiedzialnym za to zdarzenie, który powinien wyglądać następująco.

private void btnSubmit_Click(object sender, System.EventArgs e)
{
}

Dodajemy teraz wnętrze, dzięki któremu utworzymy sesje i wyegzekwujemy procedurę odpowiedzialną za załogowanie się.

private void btnSubmit_Click(object sender, System.EventArgs e)
{
     // wywolanie procedury
     bool boolLogin = StudentLogin (txtLogin.Text, txtPassword.Text);
     // jesli haslo i login jest poprawny i zgodny
     if (boolLogin)
     {
          // utworzenie sesji
          Session["Student"] = txtLogin.Text;
          // przekierowanie na strone domslna
          FormsAuthentication.RedirectFromLoginPage
          (
               txtLogin.Text, false
          );
     }
     // wypisanie komunikatu o bledzie
     else
     {
          labError.Text = "Login Failed!";
     }
}

Ostatni etap to wypisanie informacji o zalogowanym użytkowniku, na stronie zabezpieczonej. W tym celu należy przejść na WebForm2.aspx.cs i wpisać odrobinę kod w metodzie odpowiedzialnej za ładowani strony, tak aby wyglądała następująco.

private void Page_Load(object sender, System.EventArgs e)
{
     // przypisanie etykicie loginu użytkownika
     labInfo.Text = "" + Session["Student"];
}

Teraz wystarczy w widoku Solution Explorer nacisnąć prawym guzikiem myszy na WebForm2.aspx i wybrać opcje Set As Start Page. Opcja ta jest potrzebna, aby przy ładowaniu najpierw pojawiła się strona logowania chroniąca stronę z danymi. W przeciwnym wypadku nastąpi włączenie strony logowania bez przekierowania po poprawnym wpisaniu hasła.

I co dalej?

Teraz, kiedy możemy już przeprowadzać skuteczne uwierzytelnianie za pomocą „Forms authentication”, możemy poeksperymentować z innymi sposobami. Ale to już temat na następny artykuł. Kolejnym zagadnieniem dotyczącym tej samej dziedziny jest przerzucenie ciężaru sesji z pamięci serwera na bazę danych. To rozwiązanie przeznaczone jest dla aplikacji odwiedzanych przez wielu użytkowników i powodujących znaczne obciążenie pamięci serwera. Te zagadnienia będą tematem następnego artykułu, oczywiście jeżeli ten się spodoba i będzie zapotrzebowanie na takie tematy.

W materiałach dodatkowych dołączyłem działający program napisany w języku C# oraz VB, a także skrypty SQL tworzące bazę danych i dodające użytkownika do bazy wraz z przydzieleniem mu dostępu wykonywania procedury.

Załączniki:

Podobne artykuły

Komentarze 10

godlewm1609
godlewm1609
3 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
Podobało się. Przyzwoity temat dla początkujących programistów, niby proste rzeczy, a jednak trudne do znalezienia - dlatego 6. Małe zastrzeżenie - w niektórych miejscach artykułu odczuwa się odbieganie od tematu.
:)
:)
3 pkt.
Nowicjusz
:)
21-01-2010
oceń pozytywnie 0
artykuł jest w rzeczy samej jakiś... chaotyczny, niezrozumiały i co innego jest napisane w tytule a o czym innym pisze autor
User 79355
User 79355
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
...dla kogos kto zaczyna zabawe z ASP.NET dosc wartosciowy artykul. Sam sporo sie naszukalem zanim znalazlem jak to sie robi, jednak jakosc artykulu troche jest nie do konca dopracowana.
sebastiancodeguru851
sebastiancodeguru851
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
artykuł dobry na piątkowe popołudnie :)
User 79209
User 79209
2 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
Ogromnie duzo niejasnosci, ktore osobe nie obeznana z tematem moga wprowadzic w blad. Przyklad: // przekierowanie na strone domslna FormsAuthentication.RedirectFromLoginPage nie nad domyslna, a ta z ktorej wystapilo przekierowanie.
User 79899
User 79899
35 pkt.
Poczatkujacy
21-01-2010
oceń pozytywnie 0
Dla początkująch jak najbardziej ok. Plus za prowadzenie za rączkę :). Minus za słownictwo.. dość często zaczynasz akapit od słowa teraz. Poza tym popieram moderatora w kwesti komentarzy. Powinienes je wziasc wtopić w część artykułu. Jednak to nie jest portal dla polonistów wobec czego piąteczka zasłużona :)
arekcaban
arekcaban
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
nie jest taki zły...
Artur Molenda
Artur Molenda
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
Jak dla mnie artukuł ciekawy, ale trochę nie na temat. Po tytule spodziewać można było się raczej opsu budowy pliku web.config, a tymczasem jest on bardzo ogólnikowy. Sama idea artykułu jest jednak bardzo interesująca, dał bym mu jednak po prostu inny tytuł na przykład: twrzenie szfrowanego połączenia z bazą danych. Podsumowując więc artykuł interesujący, ale średnio na temat
mozejkopawel
mozejkopawel
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
powiem tak: nieco administruję i programuję. ten artukuł jest pelen niescislosci i niejednoznacznosci. wydjae sie ze autor zaklada znajomosc tematyki od czytelnika. ale w takim razie po co by byl artykul?!?
testa1435
testa1435
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
Jeszcze się uczę, ale lektura artykułu nie specjalnie mi pomogła...
pkt.

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.