TIN Techniki Internetowe Lato 2005 Grzegorz Blinowski Instytut Informatyki Politechniki Warszawskiej
Plan wykładów 2 Intersieć, ISO/OSI, protokoły sieciowe, IP 3 Protokoły transportowe: UDP, TCP 4 Model klient-serwer, techniki progr. serwisów 5 Protokoły aplikacyjne: telnet, ftp, smtp, nntp, inne 6, HTTP 7, 8 HTML, XML 9, 10, 11 Aplikacje WWW, CGI, sesje, serwery aplikacji serwlety, integracja z backended SQ 12 XML, RDF, SOAP, WSDL, ontologie 13 Aspekty zaawansowane: wydajność, przenośność, skalowalność; klastering 14-15 Wstęp do zagadnień bezpieczeństwa (IPSec, VPN, systemy firewall) oraz aspekty kryptograficzne (DES, AES, RSA, PGP, S/MIME), tokeny i akceleracja sprzętowa
Aplikacje Web - przypomnienie Omówione: Podstawowe odmiany serwerów aplikacji Sesje tworzenie sesji bezpieczeństwo sesji Warstwa prezentacji Pobieranie danych z form. klienckich Generowanie HTML/XML Pozostało: Serwlety połączenie ze źródłami (bazami) danych
Serwlety
Serwlety Serwlety tworzone w języku Java są jednym z popularniejszych sposób tworzenia aplikacji Web Zalety: dostępne funkcje do obsługi typowych czynności mechanizm stosunkowo ustandaryzowany mechanizm uniwersalny i łatwo rozszerzalny stosunkowo bezpieczne Wady w bardziej złożonych środowiskach wydajność może pozostawiać wiele do życzenia (wymagania na RAM, garbage collection) "serwlet serwletowi nierówny" - istotne różnice pomiędzy różnymi środowiskami bazującymi na serwletach (np. por. - Tomcat, Oracle App. Server, IBM Websphere)
Serwlety - podstawy Definicja: Serwlet to program napisany w języku Java, ładowany i wykonywany poprzez serwer WWW lub serwer aplikacji współpracujący z serwerem WWW Klient Serwer WWW HTTP Przeglądarka Servlet Serwlet wykonuje się w środowisku serwera WWW (aplikacji) i nie może funkcjonować autonomicznie Serwer WWW musi być przygotowany do obsługi serwletów Java (np. serwery Apache, Sun/iPlanet)
Serwlety - podstawy http://java.sun.com/products/servlet/docs.html JSWDK (Java Server Web Development Kit) -podstawowy engine obsługi serwletów oraz JSP JSDK (Java Servlet Development Kit - zestaw klas do obłsugi serwletów Klasy serwletów (abstrakcyjne klasy Java): GenericServlet - obsługuje dowolne żądania niezależnie od protokołu HTTPServlet - dedykowany do obsługi HTTP Podstawowe pakiety JSDK to: javax.servlet, javax.servlet.http Servlet GenericServlet HTTPServlet MyCustomServlet
Jak działa servlet? Serwer WWW zostaje skonfigurowany do rozpoznawania URI serwletu (odróżnienia stron statycznych i dynamicznych) Serwer otrzymuje żądanie klienta, identyfikuje obsługujący je serwlet, generuje obiekt ServletRequest i uruchamia serwlet tworząc nowy wątek - Jeśli serwlet nie był jeszcze uruchamiany serwer zainicjalizuje go wywołując funkcję Init() Serwlet przetwarza ServletRequest, generuje obiekt ServletResponse Klient Przeglądarka HTTP request HTTP response Servlet Request Servlet Response Serwer Serwlet
Podstawowe API Serwletu void Init (ServletConfig config) Wołana przez serwer w momencie pierwszej aktywacji serwletu, inicjalizuje trwałe dane serwletu void Service (ServletRequest req, ServletResponse res) Wywoływana przez serwer w odpowiedzi na żądanie klienta W serwlecie HTTP wywołuje metody odpowiadające odpowiednim poleceniom HTTP garbage collection Init() config Service() dopost() doget() void Destroy () Usuwa serwlet i odzyskuje pamięć Destroy()
Tworzenie serwletów W celu wprowadzenia funkcjonalności do serwletu należy zdefiniować funkcje doxxx obsługujące konkretny typ żądania HTTP: Protected void doxxx (ServletRequest req, ServletResponse res) brak funkcji dla danej metody HTTP wygeneruje dla klienta komunikat HTTP Bad Request w przypadku próby jej użycia Funkcje: GET -> doget(httpservletrequest, HttpServletResponse) POST -> dopost(httpservletrequest, HttpServletResponse) PUT -> doput (HttpServletRequest, HttpServletResponse) DELETE -> dodelete (HttpServletRequest, HttpServletResponse) TRACE -> dotrace (HttpServletRequest, HttpServletResponse) OPTIONS -> dooptions (HttpServletRequest, HttpServletResponse)
Wzór serwletu import java.io.*; import javax.servlet.*; import javax.servlet.http.*; Co najmniej jedna funkcja obsługi musi być jawnie zdefiniowana public class ServletTemplate extends HttpServlet { public void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { // Use "request" to read incoming HTTP headers // (e.g. cookies) and HTML form data (e.g. data the user // entered and submitted). // Use "response" to specify the HTTP response status // code and headers (e.g. the content type, cookies). } } PrintWriter out = response.getwriter(); // Use "out" to send content to browser Strumień wyjściowy służy do wysłania rezultatów do klienta
Przykładowy serwlet import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloServlet extends HTTPServlet { public void doget ( ServletRequest req, ServletResponse res ) throws ServletException, IOException { res.setcontenttype( text/html ); ServletOutputStream out = res.getoutputstream()); } out.println( <html><head><title>test</title></head>"); out.println( <body> ); out.println( <h1>hello World</h1> ); out.println( </body></html> ); out.close(); }
Funkcje doxxx Wywoływane przez servlet() sama funkcja servlet() rzadko jest redefiniowana Muszą działać poprawnie w środowisku wielowątkowym synchronizować dostęp do zmiennych globalnych nienajlepsze rozwiązania ze względu na wydajność: public synchronized void doxxx(httpservletrequest req, HttpServletResponse res) lepiej zidentyfikować i wykorzystywać sekcje krytyczne nie korzystać z funkcji wykorzystujących zm. globalne lub działać w środowisku STM (Single Thread Model) - poświęcając wydajność (praktycznie ma sens tylko w w zastosowaniach testowych)
Uzyskiwanie informacji od klienta Pobranie zmiennej z formularza: wszystkie nazwy: public String ServletRequest. getparameternames() dana zmienna: public String ServletRequest.getParameter(String name) dana zmienna wielowartościowa: public String[] ServletRequest.getParameterValues (String name) Adres IP / Hostname klienta: public String ServletRequest.getRemoteAddr() public String ServletRequest.getRemoteHost() Informacja o autentykowanym użytkowniku: public String ServletRequest.getRemoteUser()
Dane klienta - przykład [1] import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class ParameterSnoop extends HttpServlet { public void doget(httpservletrequest req, HttpServletResponse res) throws ServletException, IOException { res.setcontenttype("text/plain"); PrintWriter out = res.getwriter(); out.println("query String:"); out.println(req.getquerystring()); out.println(); out.println("request Parameters:"); Enumeration enum = req.getparameternames();
Dane klienta - przykład [2] } while (enum.hasmoreelements()) { String name = (String) enum.nextelement(); String values[] = req.getparametervalues(name); if (values!= null) { for (int i = 0; i < values.length; i++) { out.println(name + " (" + i + "): " + values[i]); } } }
Generowanie odpowiedzi Musimy wygenerować: kod i string statusu: public void HttpServletResponse.setStatus(int sc) public void HttpServletResponse.setStatus(int sc, String sm) nagłówki HTTP: public void ServletResponse.setContentType(String type) Np: res.setcontenttype( text/html ); public void HttpServletResponse.setHeader(String name, String value) public void HttpServletResponse.setIntHeader(String name, int value) public void HttpServletResponse.setDateHeader(String name, long date) ciało odpowiedzi (entity body)
Generowanie odpowiedzi - entity body Generowany może być HTML, ale także np. grafika w różnych formatach(!) Należy obliczyć ContentLength (o ile serwer WWW tego nie zrobi automatycznie) Wynik generujemy korzystając ze strumienia: ServletOutputStream getoutputstream () Przykład: ServletOutputStream out = res.getoutputstream()); out.println( <html><head><title> Test </title> </head>"); out.println( <body> );
Sesje w serwletach Serwlety posiadają wbudowany mechanizm sesji Sesję definiuje klasa HttpSession Pobieranie danych sesji (tworzenie sesji przy pierwszym wywołaniu): public HttpSession HttpServletRequest.getSession (boolean create) Dodanie danej do sesji:public void HttpSession.putValue(String name, Object value) Pobranie danej / danych z sesji: public Object HttpSession.getValue(String name) public String[] HttpSession.getValueNames() Usunięcie danej z sesji: public void HttpSession.removeValue(String name)
Więcej o sesjach Sesje posiadają domyślny timeout (30 min) Serwlet może zniszczyć sesje wywołując: public void HttpSession.invalidate() Sesje serwletów nie powinny być wykorzystane do przechowywania danych trwałych Realizacja sesji: Każda sesja ma unikalny ID Sesja realizowana jest poprzez cookie lub (jeśli klient nie obsługuje) poprzez modyfikację URL-i
Zalety (i wady) stosowania serwletów Serwlety są (teoretycznie) wydajniejsze w sensie szybkości przetwarzania niż CGI oraz mechanizmy skryptowe-interpretowane (Perl, PHP,...): serwlety są kompilowane - szybkie(!), ale: serwlety często wymagają znacznego narzutu RAM/CPU do efektywnej realizacji dla prostych i średnio złożonych aplikacji serwlety mogą okazać się mniej wydajne niż proste mechanizmy Java sandbox - serwlety są bezpieczniejsze niż Perl, Niezależność od platformy: niestety argument czysto teoretyczny - kod w "czystym" C/C++ lub Perl-u jest bardziej przenośny niż Java
Zalety (i wady) stosowania serwletów Dobry model programistyczny: wielowątkowość elegancka obsługa wyjątków (wynika bezpośrednio ze stosowania Javy) Wszystkie niezbędne mechanizmy: obsługa wszystkich metod HTTP sesje cookies Mogą obsługiwać inne protokoły poza http: ftp, nntp, smtp Rozpowszechniona metodologia, duża liczba komercyjnych i darmowych implementacji, bibliotek, aplikacji,
Integracja ze źródłami danych (m.in. SQL)
Zewnętrzne źródła danych Prawie każda nietrywialna aplikacja wymaga korzystania z zewnętrznych źródeł danych Źródła danych: bazy plikowe/tekstowe - mechanizm najprostszy i dla większych objętości danych niewystarczający - konieczność sekwencyjnego przetworzenia pliku, bazy plikowe/ustrukturalizowane- mechanizm wystarczający dla stosunkowo prostych modeli danych, typowo - jedna-kilka "tabel", np. "Berkeley DB" (DBM) bazy relacyjne - wykorzystywane do przechowywania informacji w postaci "tabelarycznej", dane: personalne, finansowe, szeregi czasowe pochodzenia fizycznego, i szereg innych bazy LDAP - katalogi użytkowników i pokrewnych danych "serwisy" (Web services): RPC (SOAP/XML), RDS,...
Relacyjne bazy danych Najbardziej typowy i uniwersalny mechanizm przechowania danych trwałych Dostępnych szereg darmowych (MySql, PostgreSQL) jak i komercyjnych systemów (Oracle, Microsoft SQL Server, IBM DB2, Sybase) Dostęp do bazy odbywać się może na dwa sposoby: sterownik natywny - przeznaczony dla konkretnej bazy - wydajny, nie przenosny (przywiązany do systemy BD, platformy, języka) sterownik uniwersalny: ODBC, ADO, JDBC Serwery aplikacji "przykrywają" sterowniki BD udostępniając własny interfejs RDB/SQL
RBD - najważniejsze pojęcia Relacyjna baza danych składa się z tabel zwanych relacjami Tabela składa się z rekordów (rzędów) o identycznej postaci, Pojedyńczy rekord określony jest poprzez swoje atrybuty - np. {nazwisko:string, imie:string, wiek: integer, id: integer} Baza danych to zbiór tabel rozumianych jako: definicje danych same dane System RBD może zawierać wiele niezależnych baz
RBD - najważniejsze pojęcia Dane zawarte w tabelach mogą być powiązane, np: osoba:{id: ID, nazwisko: string, imie:string}, szef:{id: ID, zwierzchnik: ID} powiązania mogą mieć postać: 1-1 - np. dane uzupełniające pracownika n-1 - np. słownik 1-n, np. klienci obsługiwani wyłącznie przez pracownika n-m - np. klienci obsługiwani przez pracownika\ów Klucz główny - identyfikuje jednoznacznie rekord w tabeli, klucz może tworzyć jeden lub więcej atrybutów
RBD - najważniejsze pojęcia Prócz tabel baza danych może zawierać: Indeksy - indeksowanie wybranych kolumn tabeli, zwłaszcza kluczy/ klucza głownego znacząco poprawia szybkość obsługi zapytań Kod wykonywalny (procedury SQL) perspektywy (views) - tabele wirtualne zdefiniowane jako (tabelaryczny) rezultat konkretnego zapytania akcje (triggers) - konkretne zdarzenie (np. modyfikacja danej tabeli wywołuje konkretną akcję) prawa dostępu do danych
SQL Język zapytań i definicji danych oparty na języku naturalnym: SELECT * FROM osoby - zwróć wszystkie rekordy z tabeli osoby SELECT nazwisko FROM osoby WHERE imie='jan' - zwróć wszystkie nazwiska osób o imieniu "Jan" SELECT P.nazwisko FROM P osoby, S szef WHERE P.id=S.id AND S.zwierzchnik=101 - zwróć nazwiska osób, których zwierzchnik ma id = 101 INSERT INTO osoby (id, nazwisko, imie, wiek) VALUES ('kowalski', 'Jan', 1, 27) - wstaw rekord do bazy
SQL w aplikacjach Web Kroki: Nawiązanie połączenia z bazą danych Skonstruowanie zapytania Odczytanie i zwrócenie odpowiedzi Problemy: utrzymanie trwałego (niezależnego od połączeń klienckich) połączenia z RBD - nawiązanie połączenia jest b. kosztowne efektywność zapytań zwłaszcza przy znacznej wielkości zwracanych danych (kursory, paging) bazpieczeństwo danych w RBD - "SQL injection"
SQL w aplikacjach Web - Przykład PHP <? // Start PHP // Connect to MySQL Server $db = mysql_connect("localhost", "httpd", ""); // Select the Database mysql_select_db("persons", $db);?> // End PHP Fragment kodu PHP tworzącego stronę HTML - PHP między znacznikami <? oraz?> Zmienna db - deskryptor połączenia z RBD łącząc się z bazą podajemy: adres serwera i nazwę instancji po połączeniu wybieramy bazę
SQL w PHP <? // Start PHP $query = "SELECT nazwisko, imie FROM P osoby, S szef WHERE P.ID = S.ID AND P.wiek = '$wiek' AND S.zwierzchnik = '$id_szefa'";?> // End PHP Fragment kodu PHP budującego zapytanie (w postaci stringu) sens zapytania: wybierz nazwiska i imiona osób, których wiek większy od zadanego wieku i szef ma id równe zadanemu $mysql_result = mysql_query($query, $db); while($row = mysql_fetch_array( $mysql_result)) { print( <TR><TD>$row[0]</TD> ) print( <TD>$row[1]</TD></TR> ); } Wykonaj zapytanie i wyświetl wyniki Przekaż zmienną $query jako zapytanie Wyświetl dwa pierwsze atrybuty (nazwisko imię) każdego rekordu wyniku