R07_05.PDF
(
508 KB
)
Pobierz
Szablon dla tlumaczy
W tym rozdziale:
•
Uwierzytelnianie użytkownika
•
Ukryte pola danych formularza
•
Trwałe cookies
•
Śledzenie sesji API
Rozdział 7.
Śledzenie sesji
HTTP jest protokołem bezstanowym: nie ma wbudowanej funkcji, która umożliwiałaby serwerowi
rozpoznawanie, że cała sekwencja pochodzi w całości od tego samego użytkownika. Zwolennicy
poszanowania prywatności mogą postrzegać taką sytuację pozytywnie, jednakże większość
programistów WWW uważa to za wielki kłopot, jako że aplikacje WWW nie są bezstanowe.
Rozbudowane aplikacje WWW muszą współdziałać z klientem zarówno wstecznie jak i z
wyprzedzeniem, zapamiętując informacje o nim pomiędzy zleceniami. Klasycznym przykładem
może tutaj być aplikacja koszyka zakupów — klient musi mieć możliwość wkładania artykułów
do swojego wirtualnego koszyka, a serwer musi zapamiętać te artykuły, aż do czasu kiedy klient
wyloguje się kilka stron zleceniowych później (często trwa to nawet kilka dni!).
Problem stanu HTTP można najlepiej zrozumieć wyobrażając sobie szerokie forum dyskusji, na
którym jesteśmy gościem honorowym. Następnie wyobraźmy sobie, na tym forum, dziesiątki
internautów rozmawiających z nami w tym samym czasie. Wszyscy zadają nam pytania,
odpowiadając na nasze, powodując że klepiemy w klawiaturę jak opętali usiłując odpowiedzieć
wszystkim. Teraz wyobraźmy sobie, z kolei, że kiedy ktoś do nas pisze forum dyskusyjne nie
podaje jego tożsamości, jedyne co widzimy to mieszanina pytań i odpowiedzi. W forum tego typu
najlepsze co możemy zrobić to prowadzenie prostych konwersacji, np. poprzez odpowiadanie na
bezpośrednie pytania. Jeżeli będziemy próbowali zrobić coś więcej, np. zadać swoje pytanie, może
okazać się, że nie będziemy wiedzieli w którym momencie nadejdzie odpowiedź. Na tym właśnie
polega problem stanu HTTP. Serwer HTTP „widzi” tylko serię zleceń, potrzebuje więc
dodatkowej pomocy aby dowiedzieć się kto właściwie składa zlecenie
.
*
Rozwiązaniem, jak już może się zdążyliśmy domyśleć, jest przedstawienie się klienta w momencie
składania każdego zlecenia. Każdy klient musi dostarczyć niepowtarzalny identyfikator, który
umożliwi serwerowi jego identyfikację, mogą to być również informacje, które pozwolą
serwerowi poprawnie obsłużyć zlecenie. Wykorzystując przykład forum dyskusji, każdy uczestnik
musi rozpocząć swoje każdą wypowiedź od czegoś na wzór: „Cześć, Mam na imię Jason i...” lub
„Cześć, właśnie zapytałem o twój wiek i...”. Jak się przekonamy podczas lektury tego rozdziału,
istnieje wiele sposobów umożliwiających klientom „HTTP-owym” na przesłanie wstępnych
informacji wraz z każdym zleceniem.
Pierwsza połowa tego rozdziału poświęcona będzie tradycyjnym technikom śledzenia sesji,
wykorzystywanych przez programistów CGI: uwierzytelnianie użytkownika, ukryte pola danych
formularza, przepisywanie URL-u oraz trwałe cookies. Natomiast druga połowa rozdziału omawia
wbudowaną obsługę dla śledzenia sesji w Interfejsie API. Obsługa ta jest zbudowana na szczycie
tradycyjnych technik i znacznie upraszcza zadanie śledzenia sesji w naszych apletach. Wszystkie
omówienia zawarte w tym rozdziale opierają się na założeniu, że używany jest serwer pojedynczy.
Rozdział 12 „Aplety Przedsiębiorstw i J2EE” wyjaśnia jak jest realizowana obsługa stanu
wspólnej sesji w serwerach wielo-wejściowych.
Uwierzytelnianie użytkownika
Jednym ze sposobów przeprowadzenia śledzenia sesji jest wykorzystanie informacji pochodzącej z
uwierzytelniania użytkownika. Uwierzytelnianie użytkownika zostało omówione w rozdziale 4
„Odczytywanie Informacji”, jednak w celu przypomnienia, uwierzytelnianie użytkownika
stosowane jest kiedy serwer WWW ogranicza dostęp do niektórych ze swoich zasobów tylko do
tych klientów, którzy logują się przy użyciu określonego hasła i nazwy użytkownika. Po
zalogowaniu się klienta, nazwa użytkownika jest dostępna dla apletu poprzez metodę
getRemoteUser()
.
Możemy wykorzystać nazwę użytkownika do śledzenia sesji klienta. Kiedy użytkownik już się
zaloguje, przeglądarka pamięta jego nazwę i odsyła ją wraz z hasłem kiedy użytkownik przegląda
kolejne strony witryny WWW. Aplet może zidentyfikować użytkownika wykorzystując jego
nazwę, tym samym może również wyśledzić jego sesję. Dla przykładu kiedy użytkownik doda coś
do swojego wirtualnego koszyka na zakupy, fakt ten może zostać zapamiętany (we wspólnej klasie
lub np. w zewnętrznej bazie danych) i wykorzystany w przyszłości przez inny aplet — kiedy
użytkownik wejdzie na stronę końcową.
Aplet, który wykorzystuje uwierzytelnianie użytkownika, mógłby dla przykładu dodać artykuł do
koszyka użytkownika, przy pomocy następującego kodu:
*
Jeżeli ktoś zastanawia się nad tym, dlaczego serwer HTTP nie może zidentyfikować klienta poprzez adres
IP komputera łączącego, odpowiedź brzmi: zgłoszonym adresem IP może być adres serwera pośredniczącego
lub serwera, który obsługuje wielokrotnych użytkowników.
String name = req.getRemoteUser();
if (name == null) {
// Wyjaśnij, że administrator serwera powinien chronić tą stronę
}
else (
String[] items = req.getParameterValues("artykuł");
if (items != null) {
for (int i = 0; i < items.length; i++) (
addItemToCart(name, items[i]) ;
}
}
}
Inny aplet, może w przyszłości odczytać artykuły z koszyka zakupów za pomocą następującego
kodu:
String name = req.getRemoteUser();
if (name == null) {
// Wyjaśnij, że administrator serwera powinien chronić tą stronę
}
else (
String[] items = getItemsFromCart(name);
}
Największą zaletą wykorzystywania uwierzytelniania użytkownika w celu przeprowadzania
śledzenia sesji jest prosta implementacja. Po prostu mówimy serwerowi, żeby chronił określony
zestaw stron (zgodnie z instrukcjami z rozdziału 8 „Bezpieczeństwo”), a następnie stosujemy
metodę
getRemoteUser()
w celu identyfikacji każdego klienta. Kolejna zaleta jest taka, iż
technika ta działa nawet kiedy użytkownik wchodzi na naszą stronę z różnych komputerów.
Technika ta działa również kiedy użytkownik nie łączy się z naszą witryną lub kiedy zamyka
przeglądarkę przed powrotem na naszą stronę.
Największym mankamentem uwierzytelniania użytkownika jest fakt, iż każdy użytkownik musi
zarejestrować się na konto, a następnie logować się za każdym razem kiedy odwiedza naszą
witrynę. Większość użytkowników toleruje rejestrowanie i logowanie się jako zło konieczne kiedy
uzyskują dostęp do informacji poufnych, jednakże w przypadku zwykłego śledzenia sesji jest to
prawdziwa uciążliwość. Kolejna uciążliwość to fakt, że podstawowe uwierzytelnianie HTTP nie
zapewnia żadnego mechanizmu wylogującego; użytkownik musi zamknąć swoją przeglądarkę
żeby się wylogować. Problemy, w przypadku uwierzytelniania użytkownika stwarza niemożność
utrzymania przez użytkownika więcej niż jednej sesji na tej samej stronie (witrynie) WWW.
Wniosek z powyższych rozważań nasuwa się sam: koniecznie potrzebujemy innych rozwiązań dla
obsługi śledzenia anonimowego konta i dla obsługi uwierzytelnionego śledzenia sesji z
wylogowaniem.
Ukryte pola danych formularza
Jednym ze sposobów obsługi śledzenia anonimowego konta jest zastosowanie ukrytych pól
danych formularza. Jak sama nazwa wskazuje, są to pola dodane do formularza HTML, które nie
są wyświetlane w przeglądarce klienta. Pola te są odsyłane do serwera, kiedy formularz
zawierający je, zostaje przedłożony. Ukryte pola danych formularza dołączamy przy pomocy
HTML-u podobnego do poniższego:
<FORM ACTION="/ servlet /MovieFinder" METHOD="POST">
...
<INPUT TYPE=hidden NAME="zip" VALUE=" 94040 ">
<INPUT TYPE=hidden MAME="poziom" VALUE="expert">
...
</FORM>
W pewnym sensie ukryte pola danych formularza definiują zmienne stałe dla formularza. Dla
apletu otrzymującego przedłożony formularz nie ma żadnej różnicy pomiędzy ukrytym polem
danych a polem, które jest widoczne.
Przy zastosowaniu ukrytych pól danych formularzowych, możemy przepisać nasze aplety koszyka
zakupów, tak że użytkownicy będą mogli dokonywać zakupów anonimowo, do czasu
zakończenia. Na przykładzie 7.1 została zaprezentowana technika wykorzystująca aplet, który
wyświetla zawartość koszyka zakupów użytkownika i pozwala użytkownikowi na dodanie
większej liczby artykułów lub na zakończenie zakupów. Przykładowy widok ekranu został
przedstawiony na rysunku 7.1.
Przykład 7.1.
Śledzenie sesji przy użyciu ukrytych pól danych formularza
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ShoppingCartViewerHidden extends HttpServlet {
public void doGet(HttpServletReguest req, HttpServletResponse res)
throws ServletException, IOException {
res. setContentType (" tekst/html") ;
PrintWriter out = res.getWriter();
out.println("<HEAD><TITLE>Current Shopping Cart
Items</TITLE></HEAD>");
out.println("<BODY>") ;
// Artykuły z koszyka przekazywane są jako parametr artykułu.
String [ ] items
=
req.getParameterValues ("artykuł") ;
// Drukuj bieżące artykuły z koszyka.
out.println("Aktualnie w swoim koszyku masz następujące artykuły
cart:<BR>");
if (items == null) {
out.println("<B>None</B>") ;
}
else (
out.println("<UL>") ;
for (int i = 0; i < items.length; i++) {
out.println("<LI>" + items[i]);
}
out.println"</UL>") ;
}
// Spytaj czy użytkownik chce jeszcze dodać jakieś artykuły, czy
też // chce zakończyć.
// Dołącz bieżące artykuły jako ukryte pola danych, tak żeby mogły
być // przekazane.
out.println("<FORM ACTION=\"/servlet/ShoppingCart\" METHOD=POST>");
if (items != null) {
for (int i = 0; i < items.length; i++) {
out.println("<INPUT TYPE=HIDDEN NAME="artykuł" VALUE=\"" +
items[i] + "\">");
}
}
out.println("Chciałbyś<BR>");
out.println("<INPOT TYPE=SUBMIT VALUE
=\"
Dodaj Więcej Artykułów \">");
out.println("<INPUT TYPE=SUBMIT VALUE=\" Zakończ \">");
out.println("</FORM>")
out.println("</BODY></HTML>");
}
}
Rysunek 7.1.
Zawartość koszyka na zakupy
Plik z chomika:
lazarusp22
Inne pliki z tego folderu:
uukjsrpa.zip
(2849 KB)
uukjsrpc.zip
(2849 KB)
uukjsrpb.zip
(2849 KB)
R06_05.PDF
(842 KB)
R04_05.PDF
(597 KB)
Inne foldery tego chomika:
Java Servlet i Java Server Pages
Java Servlet. Programowanie
Java.Servlet.i.Java.Server.Page.SPECIAL.Tech-eBook-Uuk
Zgłoś jeśli
naruszono regulamin