Aleksander Timofiejew
Transkrypt
Aleksander Timofiejew
Ćwiczenie laboratoryjne „Komunikacja z serwerem w języku PHP” Tematy ćwiczenia przesyłanie na serwer danych i plików, odnośniki. ciasteczka (cookies), sesja. Sprawozdanie Na każdym zajęciu laboratoryjnym sporządza się za pomocą edytora Word sprawozdanie na bazie materiałów ćwiczenia. Bazowa zawartość sprawozdania musi być przygotowana w domu przed ćwiczeniem. W czasie ćwiczenia do sprawozdania są dodawane wyniki testowania. Treść sprawozdania: strona tytułowa, spis treści sporządzony za pomocą Word'a, dla każdego punktu rozdziały "Zadanie ", "Opracowanie zadania" (rozdział ze skryptem i komentarzami), "Testowanie" (rozdział z opisem danych wejściowych i wynikami testowania, w tym zrzuty okna przeglądarki). Wzorzec strony tytułowej znajduje się w pliku Strona_tytulowa_niestac_Interpr_jezyki_progr.doc. Nazwa pliku ze sprawozdaniem musi zawierać skrót "IJP_", numer ćwiczenia i nazwisko studenta (bez polskich liter, żeby można było archiwizować). Pliki ze sprawozdaniem są przekazywane do archiwum grupy. Wyniki opracowania zadań pokazywać za pomocą przeglądarek: Firefox Mozilla, Internet Explorer, Google Chrome lub Opera. W przypadku stosowania Firefox Mozilla używać konsoli błędów (Narzędzia/Konsola błędów). a) Przesyłanie danych klienta Zadanie Stworzyć formularz po stronie klienta do wprowadzenia imienia i nazwiska. Przyjmować i wyświetlać te dane po stronie serwera. Opracowanie zadania <pliki ze skryptami u klienta i na serwerze> Testowanie <zrzut okna> b) Przesyłanie plików klienta Zadanie Dopełnić formularz klienta możliwością wysyłania plików. Przyjmować i zapisywać do folderu DANE wysłane pliki. Opracowanie zadania <pliki ze skryptami u klienta i na serwerze> Testowanie <zrzut okna> c) Odnośniki Zadanie Wysłać na serwer identyfikator użytkownika przez odnośnik. Wyświetlić te dane po stronie serwera. Opracowanie zadania <pliki ze skryptami u klienta i na serwerze> Testowanie <zrzut okna> d) Ciasteczka Zadanie Stworzyć formularz po stronie klienta do wprowadzenia identyfikatora i zasłoniętego hasła. Zapisać w ciasteczkach przy pierwszym wywołaniu strony wysłane na serwer identyfikator i hasło. Przy nowym odwiedzeniu strony porównywać nowo wprowadzone identyfikator i hasło z zawartością ciasteczek i wydawać odpowiednie komunikaty. Opracowanie zadania <pliki ze skryptami u klienta i na serwerze> Testowanie <zrzut okna> e) Sesja Zadanie Liczyć i wyświetlać ilość odwiedzin strony. Opracowanie zadania <pliki ze skryptami u klienta i na serwerze> Testowanie <zrzut okna> Wskazówki Formularze Formularz na stronie klienta (lub serwera) jest zapisywany w znaczniku <form>. Dodatkowo zawartość formularza musi być ograniczona znacznikiem - pojemnikiem, na przykład <div>. Dane wprowadzone przez elementy formularza są wysyłane do serwera. Plik z danymi jest dostarczany do aplikacji, która musi być napisana w języku PHP (lub w podobnym języku). Dane formularza są wysyłane w przypadku naciśnięcia myszą obiektu (przycisku) "input/submit". Ponieważ wprowadzone dane zawsze są wysyłane, to znacznik <form> ma obowiązkowy atrybut action, którego wartość jest adresem URL. Inne atrybuty znacznika <form>: method do ustawienia metody przesyłania danych; enctype do ustawienia metody kodowania danych. Dla atrybutu enctype często stosowane wartości: text/plain, co oznacza "bez kodowania", oraz multipart/form-data, co oznacza "kodowanie danych formularza". Dla atrybutu method mają zastosowanie tylko dwie wartości: get, co powoduje przesyłanie danych (zawartości formularza) jako dodatku, zapisywanego poza adresem URL wskazanym w atrybucie action; post, co powoduje przesyłanie danych (zawartości formularza) w protokole HTTP. Jeśli atrybut method ma wartość get, to dodatek, zapisywany poza adresem URL, rozpoczyna się od znaku "?", a dalej są zapisywane pary "parametr=wartość", między którymi znajduje się znak "&". Znak, który nie jest literą lub cyfrą, jest zamieniany na łańcuch "%HH", gdzie HH szesnastkowy kod znaku. Dodatek, zapisywany poza adresem URL nie może być większy niż 255 znaków. W przypadku stosowania wartości get dla atrybutu method, dane są widoczne w komunikacie internetowym. Zaletą ustawienia wartości get dla atrybutu method jest podwyższona szybkość przesyłania danych. Dane przesłane przy zastosowaniu metody GET są składowane na serwerze do tablicy asocjacyjnej $_GET (dawna nazwa $HTTP_GET_VARS). Kluczem w tablicy służy wartość atrybutu name odpowiedniego elementu graficznego. Przesyłanie danych przy zastosowaniu metody POST jest bezpieczne, ponieważ dane są niewidoczne i mogą być zakodowane. Dane przesłane przy zastosowaniu metody POST są składowane na serwerze do tablicy asocjacyjnej $_POST (dawna nazwa $HTTP_POST_VARS). Kluczem w tablicy służy wartość atrybutu name odpowiedniego elementu graficznego. Tablice asocjacyjne $_GET ($HTTP_GET_VARS) i $_POST ($HTTP_POST_VARS) są globalne. Przykłady. Plik serw1.php: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso8859-2"> <title>Skrypt PHP</title> </head> <body> Info:<br/> Imię: <?php echo $_GET['imie'] ?><br /> Nazwisko: <?php echo $_GET['nazwisko'] ?><br /><br /> </body> <html> Plik test1.html: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso8859-2"> <title>Wy¶wietlił AT</title> </head> <body> <form action="http://localhost/serw1.php" method="get" enctype="text/plain" target="_blank"> <div> <input type=”text” name="imie"/>Imię<br /> <input type=”text” name="nazwisko"/>Nazwisko<br /> <input type="submit" name="uruch" value="Skrypt"> Przycisk do uruchomienia skryptu PHP na serwerze (metoda GET)</input><br /> </div> </body></html> Plik serw2.php: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso8859-2"> <title>Skrypt PHP</title> </head> <body> Info:<br/> Imię: <?php echo $_POST['imie'] ?><br /> Nazwisko: <?php echo $_POST['nazwisko'] ?><br /><br /> </body> <html> Plik test2.html: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso8859-2"> <title>Wy¶wietlił AT</title> </head> <body> <form action="http://localhost/serw2.php" method="post" enctype="multipart/form-data" target="_blank"> <div> <input type=”text” name="imie"/>Imię<br /> <input type=”text” name="nazwisko"/>Nazwisko<br /> <input type="submit" name="uruch" value="Skrypt"> Przycisk do uruchomienia skryptu PHP na serwerze (metoda POST)</input><br /> </div> </form> </body></html> Przesyłanie plików Element input/file służy do wyboru pliku u klienta. Przy odbiorze pliku na serwerze stosuje się tablica asocjacyjna $_FILES. Tablica $_FILES to dwuwymiarowa tablica asocjacyjna. Indeksowanie po wartości atrybutu name elementu input/file doprowadza do 4elementowej tablicy asocjacyjnej z kluczami: "tmp_name" - nazwa pliku (kopii pliku) umieszczonego na serwerze, "name" - nazwa pliku po stronie klienta, "size" - rozmiar pliku w bajtach, "typ" - typ internetowy pliku, tj. format MIME (Multipurpose Internet Mail Extensions), zastosowany do przesłania pliku, na przykład text/plain, image/gif itp. (W formacie MIME jest wskazywany "typ/podtyp"). Otrzymany plik jest zapisywany na serwerze jako plik tymczasowy, a odwołania do niego jest możliwe przez klucz "tmp_name". Otrzymany plik należy sprawdzić, czy był on naprawdę wysłany użytkownikiem klientem. Do sprawdzania można wykorzystywać funkcję is_uploaded_file. Oprócz tego zwykle jest sprawdzany typ pliku podawany przez klucz "typ". Do przeniesienia pliku z "tymczasowego" miejsca na miejsce "stałe" jest stosowana funkcja move_uploaded_file. Istniejący plik z takiej samej nazwą jest nadpisywany. Przykład. Plik testB.html: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd"> <html><head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2"> <title>Pliki</title> </head> <body> <form action="http://localhost/serwer.php" method="post" enctype="multipart/form-data" target="_blank"> <div> <input type="file" name="plik"> Plik</input><br /> <input type="submit" name="uruch" value="Skrypt"> Przycisk do uruchomienia skryptu PHP na serwerze (metoda POST)</input><br /> </div> </form> </body> </html> Plik serwer.php: <html><head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2"> <title>Skrypt PHP</title> </head><body> <?php $max_rozmiar = 4*1024*1024; $pfile=$_FILES['plik']; if (is_uploaded_file($pfile['tmp_name'])) { if ($pfile['size'] > $max_rozmiar) { echo 'Błąd! Plik jest za duży!'; } else { echo 'Odebrano plik. Początkowa nazwa: '.$pfile['name']; echo '<br/>'; if (isset($pfile['type'])) { echo 'Typ: '.$pfile['type'].'<br/>'; } move_uploaded_file($pfile['tmp_name'], $_SERVER['DOCUMENT_ROOT'].'/DANE/'.$pfile['name']); } } else { echo 'Błąd przy przesyłaniu danych!'; } echo "<br/><br/>"; ?></body></html> Odnosniki Parametry można przekazać do serwera za pomocą elementu "a" (odnośnika). W tym celu należy w atrybucie href umieścić nie tylko nazwę pliku PHP jako adres URL, a i dodatek z parametrami. Dodatek należy rozpoczynać od znaku "?", a dalej zapisywać pary "parametr=wartość", między którymi umieszczać znak "&". Jeżeli w dodatku jest znak, który nie jest literą lub cyfrą, to znak należy zamienić na łańcuch "%HH", gdzie HH - szesnastkowy kod znaku. Dodatek, zapisywany poza adresem URL nie może być większy niż 255 znaków. Skrypt PHP otrzymuje dane przez metodę GET, i wysłane dane znajdują się w kolekcji $_GET. Przykład. Plik testC.html: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2"> <title>Testy</title> </head> <body> <a href="http://localhost/serwer.php?ident=TEST"> Wyślij mnie</a> </body> </html> Plik serwer.php: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso8859-2"> <title>Skrypt PHP</title> </head> <body> Identyfikator: <?php echo $_GET['ident'] ?><br /><br /> </body> <html> Ciasteczka(cookies) Ciasteczko (cookie) to niewielki (rozmiarem do 4K bajtów) obiekt tekstowy w przegłądarce. Serwer może zapisać dane w ciasteczku klienta przy pierwszym odwiedzeniu strony, a dalej może poberać te dane, gdy klient ponownie odwiedzi stronę. Tym samym można zidentyfikować użytkownika, który już wchodził na serwer. Można też wyświetlić tą zawartość okienek, przy której klient zakończył popszednie odwiedzanie strony itp. Wartość ciasteczek jest przekazywana w protokole HTTP lub HTTPS przy każdym kontakcie serwera z klientem: - zawartość nowych ciasteczek w kierunku od serwera do klienta; - zawartość zapisanych ciasteczek w kierunku od klienta do serwera. Dla każdego ciasteczka jest wysyłany tekst “nazwa_ciasteczka=wartość_ciasteczka;”. Zawartość ciasteczka można przesyłać zakodowaną w protokole HTTPS. Czas istnienia ciasteczka można ustawiać na serwerze. Do zapisywania ciasteczka (cookie) jest stosowana funkcja setcookie: setcookie(nazwa_ciasteczka, wartość_ciasteczka, czas_przechowywania, ścieżka_dostępnosci_ciasteczka, domena_dostępności_ciasteczka, tryb_kodowania) Ilość argumentów można zmniejszać do jednego, tj. do "nazwa_ciasteczka". Jeżeli nie jest wskazany “czas_przechowywania”, to ciasteczka wygasają przy zamknięciu przeglądarki. Czas, do którego ciasteczko będzie przechowywane, jest liczony w sekundach od 01.01.1970. Do obliczenia czasu jest zwykle wykorzystywana funkcja time, która zwraca ilość sekund od 01.01.1970. Na bazie tej ilości można ustawić czas przechowywania ciasteczka, na przykład w ciągu jednej godziny: $czas1g=time()+3600; Argument “ścieżka_dostępnosci_ciasteczka” dotyczy ścieżki URL I zwykle jest ustawiany na wartość “/”. Argument “domena_dostępności_ciasteczka” wskazuje na domenu, która ma prawo korzystania z ciasteczka. Tą prawo mają wszystkie poddomeny danej domeny. Wartości argumentu tryb_kodowania: 0 - bez kodowania (protokół http), 1 - zastosować kodowanie (protokół https). Ciasteczka są wysyłane do klienta w nagłówku protokołu HTTP (HTTPS) przed innymi danymi. Dlatego w pliku PHP element "?php" należy umieszczać na początku, przed jakimkolwiek tekstem, a wywołanie funkcji setcookie - przed wywołaniem funkcji, powodujących wysyłanie danych do klienta, na przykład funkcji echo. Do otrzymania wartości ciasteczka należy stosować tablicę asocjacyjną $_COOKIE. Przykład: if(!isset($_COOKIE['haslo'])) {//ciasteczko “haslo” jeszcze nie istnieje setcookie('haslo',$_POST['haslo'],time()+3600); } else { $haslo=$_COOKIE['haslo']; if ($haslo=='qwer') printf('OK!<br />'); else printf('Nie OK!<br />'); } Obsługa sesji Odwiedzenia tej samej strony tworzą sesją. Sesja rozpoczyna się pierwszym odwiedzeniem i kończy się przez zamknięcie przeglądarki. Przy pierwszym odwiedzeniu strony serwer tworzy identyfikator sesji (ID) i dalej stosuje ten identyfikator do autoryzacji użytkownika (klienta). Identyfikator sesji jest przechowywany jako ciasteczko po stronie klienta, lub jest przesyłany razem z URL w parametrze PHPSESSID, jeżeli obsługa ciasteczek po stronie klienta jest wyłączona. Dla każdej sesji serwer tworzy tablicę asocjacyjną $_SESSION, z której może korzystać skrypt PHP w celu przechowywania danych sesji. Działania związane z tworzeniem obiektów sesji serwer może wykonać automatycznie, jeśli w pliku inicjalizacji php.ini jest włączona opcja auto_start. Te działania można inicjalizować przez wywołanie funkcji session_start. Lepiej zawsze wywoływać funkcję session_start, ponieważ ta funkcja sama sprawdza, czy sesja już uruchomiona przez włączoną opcję auto_start. Przykład skryptu, który liczy odwiedzenia strony: <?php session_start(); if (!isset($_SESSION['kod'])) $_SESSION['kod']=$_SERVER['REMOTE_ADDR']; if (!isset($_SESSION['ilosc'])) {// zmienna "ilosc" nie jest zarejestrowana session_regenerate_id(); $_SESSION['ilosc']=1; //początkową wartość echo 'Strona odczytana pierwszy raz.'; } else {// zmienna "ilosc" jest zarejestrowana if ($_SESSION['kod']==$_SERVER['REMOTE_ADDR']) {// kod IP jest poprawny $_SESSION['ilosc']++; echo 'Strona odczytana '.$_SESSION['ilosc'].' razy. <br /><br />'; echo 'IP='.$_SESSION['kod'].'<br /><br />'; } } ?> Wywołanie dodatkowej funkcji session_regenerate_id zwiększa odporność na włamania. Ta funkcja powoduje generowanie nowego losowego identyfikatora sesji, który zamienia identyfikator wygenerowany automatycznie. Tym samym walczymy z automatycznym generowaniem dobrze widocznego w protokole HTTP identyfikatora, jeśli strona wywołana z parametrem PHPSESSID równym niepoprawnemu identyfikatorowi, na przykład 0. W celu uniknięcia włamania w przykładzie stosuje się też zapamiętywanie koda IP klienta: if (!isset($_SESSION['kod'])) $_SESSION['kod']=$_SERVER['REMOTE_ADDR']; i porównanie kodów przy następnych odwiedzeniach strony: if ($_SESSION['kod']==$_SERVER['REMOTE_ADDR']) {// kod IP jest poprawny ... echo 'IP='.$_SESSION['kod'].'<br /><br />'; }