%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% :HTTP %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Protokol HTTP} \label{HTTP} HTTP (HyperText Transfer Protocol) je velmi oblíbený protokol pro přenos dat na internetu. Nejčastěji se používá pro přenos jednoduchých textových a~binárních dat jako jsou webové stránky a~obrázky, je však vhodný i~pro přenos souborů jako jsou dokumenty, mp3 soubory nebo video. V~Javě Enterprise Edition je využívaný pro dynamické webové stránky a~webové služby. Přestože veškerou komunikaci skrz HTTP za nás zde zajišťují technologie jako \emph{servlet kontejner} propojené s~vysokoúrovňovými frameworky, je znalost HTTP velkou výhodou. Umožní nám zvážit, co vše je, a~co naopak není možné provádět ve webové aplikaci. Usnadní nám hledání chyb a~možných rizik. Taktéž se jedná o~klíčovou technologii pro RESTful webové služby, se kterými se setkáme v~kapitole \ref{RESTful Web Services} \subsection{Komunikace prostřednictvím HTTP} HTTP je textový protokol s~definovanou syntaxí zprávy. Pokud se na něj podíváme z~hlediska referenčního modelu OSI (Open Systems Interconnection -- více v~\cite{OSI Wiki}), jedná se o~aplikační vrstvu. Doručení textové HTTP zprávy na server se realizuje pomocí TCP/IP. Všechny příklady využívající HTTP zmíněné v~této knize je možné realizovat takto nízkoúrovňově. Není to však vůbec zapotřebí. Java EE nám nabízí komfortní prostředky pro velmi snadné zasílání a~čtení HTTP zpráv. V~některých technologiích zmíněných v~následujících kapitolách to došlo tak daleko, že naivní uživatel -- programátor je natolik odstíněn od HTTP, že vůbec nemusí tušit, že tento protokol používá. \subsection{Komunikační model požadavek -- odpověď} Protokol HTTP používá pro komunikaci se serverem model \emph{požadavek -- odpověď}. V~tomto modelu se komunikace účastní pouze dva aktéři: \emph{klient} pošle svůj požadavek na \emph{server}, ten sestaví odpověď a~pošle ji klientovi. Klientem a~serverem mohou být ale i~dva počítače zapojené v~síti jako servery. Důležité je, že klient pošle svůj požadavek a~očekává odpověď. Ta mu musí přijít, i~kdyby měla být zamítavá (např. odpovědi \texttt{404 Not Found} nebo \texttt{500 Internal Server Error}). V~případě, že by odpověď vůbec nepřišla (např. pokud je server v~takovém stavu že ani nedokáže poslat odpověď), dojde k~tzv. \emph{timeoutu}. Je důležité vědět, že server nemůže nikdy klientovi samovolně poslat nic, o~co by samotný klient nepožádal. \subsection{Webový zdroj} V~terminologii HTTP se každý prvek na internetu nazývaná \emph{webový zdroj} (resource). Zdrojem může být HTML stránka, obrázek, soubor, ale i~algoritmus. Všechny požadavky klienta směřují na nějaký zdroj. \subsection{HTTP požadavek} HTTP požadavek je textová zpráva s~přesně určenou strukturou. První řádek, nazývaný \emph{Request line}, se skládá z~jména HTTP metody (v~příkladu metoda \texttt{GET} -- podrobnosti si uvedeme později) následovaného cestou k~požadovanému zdroji a~verzí HTTP kterou používáme (v~našem případě vždy verze 1.1). Další řádky se nazývají pole hlavičky (podrobnosti později). Požadavek musí končit prázdným řádkem. Zároveň všechny řádky musí končit dvojicí bajtů CR-LF (Carriage return - Line feed. V~programovacím jazyce Java se tyto bajty zapisují jako \texttt{{\textbackslash}r} a~\texttt{{\textbackslash}n}). Příklad ukazuje požadavek na zobrazení stránky \emph{index.html} známého internetového vyhledávače Google. \begin{Verbatim} GET /index.html HTTP/1.1 Host: www.google.cz Accept: text/html \end{Verbatim} \subsection{URI a~cesta ke zdroji} Každý webový zdroji má svou vlastní adresu (URI --- Unified Resource Identifier). Adresa začíná frází \emph{http://}), následuje adresa serveru a~nakonec cesta ke zdroji. Adresa serveru může být IP adresa, zpravidla se ale používá jméno z~DNS (Domain Name Service, tj. přidělení lidsky čitelných názvů IP adresám). Cesta ke zdroji připomíná adresářovou cestu (obzvláště v~operačním systému Unix) a~byla i~takto navržena. V~HTTP existují pouze absolutní cesty, všechny proto musí začínat lomítkem. Cesta ke kořenovému zdroji je \emph{/}. Příklad ukazuje jak poslat požadavek na kořenový zdroj serveru \emph{www.google.cz}. \begin{Verbatim} GET / HTTP/1.1 Host: www.google.cz Accept: text/html \end{Verbatim} \subsection{Reprezentace webového zdroje} Webový zdroj je abstraktní prvek. Pokud na něj posíláme požadavek, chceme dostat jeho tzv. reprezentaci. Reprezentací kořenového zdroje serveru \emph{www.google.cz} je HTML stránka. Reprezentací zdroje s~adresou \emph{http://www.google.cz/images/nav\_logo.png} je obrázek. \fcolorbox{boxout}{boxin}{ \parbox{0.98\linewidth}{ V~jednoduchých návrzích má každý zdroj právě jednu reprezentaci. Nemusí to ale platit obecně. Algoritmus jako webový zdroj nemá zpravidla žádnou reprezentaci. Naopak dokument může mít reprezentací více --- jednu ve formátu PDF, druhou ve formátu DOC. }} \subsection{MIME typ reprezentace} Každá reprezentace webového zdroje musí mít specifikovaný tzv. MIME typ. Jedině tak poznáme, jak reprezentaci zpracovat. Reprezentaci s~typem \texttt{text/html} (HTML stránka) předáme prohlížeči k~vykreslení. Naopak reprezentace s~typem \texttt{application/xml} bude určena pro programové zpracování. \subsection{Pole hlavičky} Druhý a~třetí řádek požadavku z~předchozího příkladu jsou \emph{pole hlavičky} (header fields). Těch může být i~více. Každé takovéto pole má svůj název a~hodnotu, oddělenou dvojtečkou. Názvy jednotlivých polí jsou pevně dané. Jejich seznam můžete nalézt v~\cite{HTTP RFC}. Zopakujme si požadavek na kořenový zdroj vyhledávače Google. \begin{Verbatim} GET / HTTP/1.1 Host: www.google.cz Accept: text/html \end{Verbatim} V~příkladu máme položky pouze dvě. Položka \texttt{Host} nám udává adresu serveru, na kterou se požadavek zasílá. Druhou položkou je \texttt{Accept}, který nám říká o~jaký MIME typ reprezentace daného zdroje máme zájem. V~našem případě chceme zobrazit webovou stránku, žádáme proto typ \emph{text/html}. Za poli hlavičky musí následovat vždy prázdný řádek. Z~hlediska programování v~Javě si lze pole hlavičky představit jako objekt typu \texttt{Map}. \subsection{HTTP odpověď} HTTP odpověď má podobnou strukturu jako požadavek. Skládá se z~prvního řádku, který uvádí základní informace o~odpovědi: verzi protokolu a~výsledek. Následují pole hlavičky ukončené prázdným řádkem. Pokud má odpověď nějaké tělo (při kladném vyřízení požadavku ho zpravidla má), je toto tělo uvedeno dále a~končí prázdným řádkem. Následující příklad ukazuje zjednodušenou odpověď, kterou jsme dostali od serveru \emph{www.google.cz} na předchozí požadavek: \begin{Verbatim} HTTP/1.1 200 OK Content-Type: text/html Google ... \end{Verbatim} V~této odpovědi jsme se dozvěděli, že požadavek byl úspěšně vyřízen (kód 200 spolu s~popiskem OK, podrobnosti později). Položka hlavičky \texttt{Content-Type} uvádí MIME typ přiloženého těla odpovědi. Toto je důležité, jelikož si v~programu nemusíme pamatovat, jaký typ jsme žádali. Nejdůležitější je ale bezesporu samotné tělo odpovědi (v~terminologii HTTP se nazývané \emph{entity}). Tím je kompletní HTML stránka (v~příkladu zjednodušena) v~podobě zdrojového kódu. Samotný HTML kód pak můžeme předat webovému prohlížeči, aby nám jej zobrazil. Všimněte si, že součástí odpovědi není adresa serveru ani cesta ke zdroji. Webový prohlížeč (nebo jiná klientská aplikace) si sám musí pamatovat, která odpověď přišla na který požadavek. \subsection{Záporná odpověď} Velmi častou odpovědí je záporná odpověď \texttt{404 Not Found} (někdy chybně zvaná 404 Page Not Found). Stává se tak velmi často u~webových stránek, které autor předělával a~výsledek po sobě dostatečně nezkontroloval. Takováto odpověď nám pak sděluje, že webový zdroj s~danou adresou neexistuje. Záporné odpovědi zpravidla neobsahují ve svém těle žádnou přílohu. Příklad ukazuje odpověď \texttt{404 Not Found}. \begin{Verbatim} HTTP/1.1 400 Not Found \end{Verbatim} \subsection{Metody požadavku} Specifikace HTTP definuje celkem osm metod: \texttt{GET}, \texttt{POST}, \texttt{HEAD}, \texttt{PUT}, \texttt{DELETE}, \texttt{TRACE}, \texttt{CONNECT} a~\texttt{OPTIONS}. Tady nastává hlavní úskalí programátora pracujícího s~HTTP, jelikož masově rozšířené jsou pouze \texttt{GET} a~\texttt{POST}. Bohužel plno serverů ani jiné metody neimplementuje a~například \texttt{PUT} požadavek zahazují. Taktéž nemalá část knihoven pro práci s~HTTP neumí vyrobit jiný požadavek, než \texttt{GET} nebo \texttt{POST}. Vzhledem k~tomuto nepříjemnému faktu si zde vysvětlíme pouze metody \texttt{GET} a~\texttt{POST}. \subsubsection{GET} \texttt{GET} je metoda určená pro získávání dat ze serveru, většinou reprezentací zdrojů. Pokud mluvíme o~zdroji, je třeba si uvědomit, že se jedná o~abstraktní prvek na webu. Nemůžeme získat zdroj jako takový, pouze jeho reprezentaci. Například webová stránka může (ale nemusí) být k~dispozici jako \emph{text/html} nebo jako \emph{application/xhtml+xml}. Už v~tomto případě se jedná o~dvě různé reprezentace. Webový prohlížeč umí zpravidla obě dvě zobrazit a~dá se čekat, že u~obou bude vizuální výsledek stejný. U~dokumentu v~\emph{application/rtf} a~v~\emph{application/pdf} už ale může být znatelný rozdíl. Metoda \texttt{GET} slouží k~získání reprezentace a~umožňuje nám si vybrat, o~kterou máme zájem (v~položce hlavičky \texttt{Accept}). Běžný uživatel internetu v~drtivé většině případů používá právě \texttt{GET} a~to k~prohlížení webových stránek nebo ke stahování souborů. Metoda \texttt{GET} byla použita v~předchozích příkladu, uveďme si ji ale ještě jedou. \begin{Verbatim} GET / HTTP/1.1 Host: www.google.cz Accept: text/html \end{Verbatim} \subsubsection{POST} Na rozdíl od \texttt{GET} je metoda \texttt{POST} navržena pro zasílání dat na server. To se formálně drží metodiky požadavek -- odpověď. Klient tedy pomocí \texttt{POST} pošle požadavek o~nahrání přiložených dat na server. Server se rozhodne, jestli data přijme nebo nikoliv a~své rozhodnutí oznámí HTTP odpovědí. Klasickým použitím metody \texttt{POST} je nákup na internetovém obchodě. Do košíku si naskládáte zboží a~pošlete na server své osobní údaje (jméno, bydliště, číslo kreditní karty,...). Tyto údaje jsou připojeny v~těle požadavku stejně, jako byl HMTL kód připojen v~kladné HTTP odpovědi. Formát připojených dat závisí na dohodě se serverem. Následující příklad ukazuje zaslání objednávky na server \emph{www.mujobchod.cz}. Cesta k~webovému zdroji zpracovávajícímu objednávku je \emph{process-order}. Objednávka je ve formátu XML určeném pro počítačové zpracování (MIME typ \texttt{application/xml}). Pro zjednodušení zde nebudeme řešit přihlašovací jméno ani heslo. \begin{Verbatim} POST /process-order HTTP/1.1 Host: www.mujobchod.cz Content-Type: application/xml Content-Length: 217 Radovan Netuka 85bc 7e44 \end{Verbatim} \fcolorbox{boxout}{boxin}{ \parbox{0.98\linewidth}{ Některé učebnice webového programování uvádějí jako klasický příklad metody \texttt{POST} zasíláni přihlašovacího jména a~hesla na server. Ač formálně je to správně, zásadně to odporuje bezpečnosti, ale i~samotnému návrhu HTTP. Správný postup při autorizaci uživatele je zcela jiný a~vysvětlíme si ho později v~této kapitole. }} \subsection{Kódy odpovědi v HTTP} Výsledek HTTP odpovědi je uveden třímístným kódem (např. 200), který bývá většinou následován svým jménem (např. OK). Je třeba mít se na pozoru, jelikož závazné jsou pouze tyto třímístné kódy. Jména mají sloužit jen jako jakési připomenutí pro uživatele (programátora), co ten který kód znamená. Mezi verzemi HTTP 1.0 a~1.1 došlo k~přejmenování některých kódů, porovnávat výslednou odpověď s~očekávaným výsledkem by se mělo vždy provádět pouze podle třímístného kódu. Specifikace HTTP zavádí velké množství těchto kódů. Jejich kompletní seznam spolu s~jejich popisy lze najít ve specifikaci \cite{HTTP RFC} nebo v~knize \cite{RESTful Web Services}. V~této kapitole si uvedeme pouze základní kódy s~nimiž se může setkat uživatel nebo vývojář webové aplikace. \subsubsection{200 OK} S~trochou nadsázky by se dalo říct, že tuto odpověď chce každý. Jedná se o~potvrzení, že požadavek byl úspěšně vyřízen. Pokud se jedná o~reakci na \texttt{GET} požadavek, měla by být v~těle odpovědi přiložena požadovaná reprezentace. Pokud přišla odpověď \texttt{200 OK} na požadavek s~metodou \texttt{POST}, znamená to, že server přijal a~zpracoval námi poslaná data. Některé webové aplikace zneužívají faktu, že odpověď \texttt{200 OK} s~přiloženou HTML reprezentací je automaticky vykreslována webovým prohlížečem a~zasílají veškeré chyby, zpracované jako webovou stránku, v~odpovědi \texttt{200 OK} namísto jejich obvyklých kódů. Toto chování, označované jako \emph{soft 404} (termín je použit v~\cite{HTTP 404 Wiki}) je velmi destruktivní jelikož maří snahy o~zpracování odpovědí programově. Pravidlo dle specifikace zní jasně: kód \texttt{200 OK} je určen pro kladné vyřízení požadavku a~jako reakce na \emph{GET} musí vždy obsahovat přiloženou reprezentaci. Jako příklad zopakujme odpověď na požadavek na vyhledávač Google. \begin{Verbatim} HTTP/1.1 200 OK Content-Type: text/html Google ... \end{Verbatim} \subsubsection{301 Moved Permanently} Odpověď \texttt{301 Moved Permanently} značí, že požadovaný zdroj byl trvale přemístěn na jinou adresu. Může jít jak o~změnu cestu ke zdroji, tak o~přemístění na úplně jiný server. Jelikož tvůrce každé webové aplikace musí počítat s~tím, že jakmile jednou adresy zdrojů v~aplikaci zveřejní, uživatelé si je můžou přidat do oblíbených položek ve svém prohlížeči. Při jakékoliv úpravě adres je pak vhodné vracet na staré adresy právě kód \texttt{301 Moved Permanently} spolu s~vyplněným polem hlavičky \texttt{Location}, které obsahuje novou adresu. \begin{Verbatim} HTTP/1.1 301 Moved Permanently Location: /newlocation \end{Verbatim} Reakcí webového prohlížeče na tuto situaci je poslat kopii požadavku na tuto novou adresu. Případný výsledek se pak zobrazuje na stejné záložce, hodnota pole pro zadávání webových adres je nahrazena novou hodnotou. \subsubsection{400 Bad Request} Kódy začínající cifrou 4 značí, že v~požadavku (nikoliv v~aplikaci na serveru) došlo k~nějaké chybě. Nejobecnějším kódem pro vyjádření této skutečnosti je \texttt{400 Bad Request}. V~kontextu, v~jakém jsme si zatím webové aplikace uváděli je tento kód určený například pro špatné data vyplněné v~metodě \texttt{POST}. Ať už jsme zkusili odeslat objednávku bez vyplněného jména nebo uvedli telefonní číslo jako text bez číslic, pro toto všechno je určen kód \texttt{400 Bad Request}. V~praxi je občas obtížné zakomponovat tento kód do webové aplikace. Pokud uživatel v~objednávce nevyplnil své jméno, je často lepší ho na tuto skutečnost upozornit jinak, než že mu jeho prohlížeč vypíše kód 400 bez jakéhokoliv komentáře. \begin{Verbatim} HTTP/1.1 400 Bad Request \end{Verbatim} Pokud je aplikace určena výhradně pro lidské uživatele (tedy nehodláme ji nikdy zpracovávat počítačově), je tolerovatelné namísto kódu \texttt{400 Bad Request} poslat \texttt{200 OK} spolu s~popisem chyby, například znovu poslat uživateli HTML stránku s~registračním formulářem, kde ho navíc červeným nápisem upozorňujeme, že zapomněl vyplnit povinné údaje. Pokud se k~tomuto postupu nechcete uchýlit, je zapotřebí využít technologie Ajax, která ovšem není součástí této knihy. \subsubsection{401 Unauthorized} Tento kód značí, že požadovaný zdroj se nachází v~chráněné oblasti a~pro přístup k~němu danou metodou je zapotřebí se prokázat uživatelským jménem a~heslem. Může jít jak o~reakci na metodu \texttt{GET}, snažící se získat například recenzi na počítačovou hru z~placených webových stránek, nebo třeba o~reakci na metodu \texttt{POST}, která se snaží nahrát takovouto recenzi na server a~ten potřebuje zkontrolovat, jestli jde o~registrovaného zaměstnance. Tento kód by měl být vrácen vždy, když se snažíte o~přístup do chráněné oblasti bez vyplnění autorizačních dat (podrobnější popis bude uveden dále v~této kapitole) anebo se špatnými autorizačními daty. Příklad uvádí odpověď \texttt{401 Unauthorized}. Její význam si probereme podrobněji později v~části o~autorizaci. \begin{Verbatim} HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm = "Private Email Account" \end{Verbatim} Reakcí webového prohlížeče na tuto odpověď je zobrazení přihlašovacího dialogového okna. \subsubsection{403 Forbidden} Jedná se o~podobnou odpověď jako \texttt{401 Unauthorized} v~tom smyslu, že požadovaná akce je nedostupná, jenom s~tím rozdílem, že autorizace zde není možná. Server nebo webová aplikace například usoudili, že uživatelské jméno ani heslo nemůžete znát a~je tedy zbytečné ho po vás žádat. Tento kód se také často využívá jako dočasné řešení při údržbě serveru. V~takovouto dobu není vhodné, aby do aplikace zasahoval kdokoliv jiný kromě správce, byť by měl na serveru vytvořený svůj vlastní účet. Příklad ukazuje odpověď \texttt{403 Forbidden}. \begin{Verbatim} HTTP/1.1 403 Forbidden \end{Verbatim} \subsubsection{404 Not Found} Kód který nám oznamuje, že požadovaný zdroj se nepodařilo najít, nese název \texttt{404 Not Found}. Často bývá chybně označován jako 404 Page Not Found. Jedná se o~reakci na požadavek \texttt{GET}, který se odkazuje na neexistující adresu. Je jedno, jestli někdo aplikaci předělal a~stránka se teď jmenuje jinak, jestli je v~adrese vypadlo jedno písmenko anebo jestli se adresa od začátku odkazuje na nějakou hloupost, pro všechny tyto případy je určen kód \texttt{404 Not Found}. Netřeba říkat, že ve výsledné fungující aplikaci si klademe mimo jiné za cíl, aby uživatel tento kód nikdy neviděl. Příklad ukazuje odpověď \texttt{404 Not Found}. \begin{Verbatim} HTTP/1.1 404 Not Found \end{Verbatim} \subsubsection{500 Internal Server Error} Kódu \texttt{500 Internal Server Error} značí, že v~aplikaci došlo k~blíže nespecifikované chybě, která mohla ochromit jak požadovaný zdroj, tak celou aplikaci. \begin{Verbatim} HTTP/1.1 500 Internal Server Error \end{Verbatim} Na místě je pak hledání chyby ze strany správce aplikace a~její odladění. Tento kód by uživatel ve výsledné aplikaci neměl nikdy vidět a~to ani za předpokladu, že provedl nějakou nestandardní akci, například ručně editoval adresu. \subsection{Bezestavovost} Protokol HTTP byl navržen jako bezestavový. To znamená, že mezi jednotlivými požadavky se neukládá žádný stav (tedy žádné parametry, objekty, identifikační čísla ani nic podobného). Nelze tedy uchovávat stav komunikace, dotazy spolu nemají souvislost. Server tak vyřídí požadavek, který dostane a~dále na celou situaci zapomene (všimněte si paralely s~běžným životem). To nám (zdánlivě) může v~některých situacích vadit. Vezměme si například problém nákupního košíku. Zákazník si do něj dá vybraný kus zboží a~prohlíží si obchod dále. Pokud se na to podíváme z~technického hlediska, posílá na server další požadavky na HTML reprezentaci jednotlivých sekcí obchodu. Očekáváme ale, že uložené zboží mu v~košíku pořád zůstane, jinak by si ho nemohl objednat. Vyvstává problém jak zařídit přenášení obsahu košíku mezi jednotlivými požadavky, když HTTP je, jak jsme si před chvílí řekli, bezestavový. Na řešení tohoto problému si budete muset počkat, ale nemějte obavy, ukážeme si hned dvě řešení, jedno pomocí tzv. \emph{sezení} v~kapitole \ref{JSP} a~druhé v~kapitole \ref{RESTful Web Services}. \fcolorbox{boxout}{boxin}{ \parbox{0.98\linewidth}{ Pozor na špatnou interpretaci bezestavovosti. Neznamená, že by jednotlivé zdroje nemohly mít vlastní stav, který by se měnil. To je naopak velice obvyklé. Bezestavovost zakazuje uchovávat stav pouze samotné komunikaci. }} \subsection{HTTP Query} Součástí cesty ke zdroji může být tzv. \emph{query}. Slouží ke specifikování parametrů a~své využití má hlavně, pokud je webovým zdrojem algoritmus. Query je připojena na konec cesty a~začíná symbolem \texttt{?}, za kterým následují dvojice klíč--hodnota. Pokud je dvojic více (zadáváme více parametrů), jsou od sebe odděleny znakem \texttt{\&}. Příklad ukazuje adresu webového zdroje, kterým je vyhledávací algoritmus Googlu. Jako parametr \texttt{q} (tak ho návrháři Googlu pojmenovali) zadáváme slovo \emph{Java}. \begin{Verbatim} http://www.google.cz/search?q=Java \end{Verbatim} Příklad rozšíříme na vyhledávání klíčového slova \emph{Java EE}. Namísto mezery se v~query udává znak \texttt{+}. Příklad po úpravě vypadá následovně: \begin{Verbatim} http://www.google.cz/search?q=Java+EE \end{Verbatim} Nakonec příklad rozšíříme o~použití dalšího parametru --- \texttt{hl} (header line). Ten specifikuje, v~jakém jazyce bude hlavička webové stránky Googlu. Jako hodnotu parametru zadáme \texttt{cs} (česky). \begin{Verbatim} http://www.google.cz/search?hl=cs&q=Java+EE \end{Verbatim} Na závěr si ukažme, jak by vypadal HTTP požadavek na zdroj prohledávacího algoritmu s~těmito parametry. Připomeňme, že query je součástí cesty ke zdroji. \begin{Verbatim} GET /search?hl=cs&q=Java+EE HTTP/1.1 Host: www.google.cz Accept: text/html \end{Verbatim} Žádné parametry s~univerzálním významem neexistují. Zadávat má cenu pouze ty parametry, které konkrétní webová aplikace umí zpracovat. Jestli má parametr nějakou implicitní hodnotu, je na návrháři aplikace. Pokud zadáme parametry, které aplikace neumí zpracovat, budou ze strany serveru ignorovány. \subsection{Autorizace a autentikace} \label{HTTP Authorization} Je celkem běžné, že ne každý zdroj ve webové aplikaci je přístupný komukoliv. Vezměme si třeba e-mailový účet -- ten by měl byt přístupný jen a~pouze jeho majiteli. Jako další příklad můžeme uvažovat databázi slov v~internetovém slovníku. Je jasné, že pokud bychom dali každému uživateli možnost ji měnit (nebo dokonce celou smazat), nebylo by z~toho nic dobrého. V~takových případech je žádoucí takovéto zdroje, nebo alespoň některé jejich metody, chránit uživatelským jménem a~heslem. Při přístupu k~chráněnému zdroji je pak nutná \emph{autorizace}. Při zaslání HTTP požadavku na chráněný zdroj musíme říct, že jsme oprávněná osoba (např. správce slovníkové databáze). To by ale mohl říct každý, následuje tedy \emph{autentikace} -- prokázání této skutečnosti správným heslem. V~reálném světě obě tyto fáze splývají v~jednu, tedy uvádíme jak uživatelské jméno, tak heslo naráz. Z~tohoto důvodu se tedy někdy celý proces nazývá zjednodušeně autorizace. \subsection{Jak probíhá autorizace v~HTTP} Předpokládejme, že se snažíme přistoupit na svou soukromou e-mailovou schránku umístněnou na internetu na adrese: \\ \emph{http://www.myexample.com/email/netuka}. \\ Pošleme tedy požadavek s~metodou \texttt{GET} tak, jak ho známe. \begin{Verbatim} GET /email/netuka HTTP/1.1 Host: www.myexample.com Accept: text/html \end{Verbatim} Namísto očekávané odpovědi \texttt{200 OK} nám ale server vrátí následující odpověď. \begin{Verbatim} HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm = "Private Email Account" \end{Verbatim} Pokud jste pozorně četli část pojednávající o~jednotlivých kódech odpovědí v~HTTP, pak vás odpověď \texttt{401 Unauthorized} nepřekvapí. Právě toto je kód, který nám sděluje, že pro přístup k~požadovanému zdroji je potřeba autorizace. Nově se ale setkáváme s~položkou hlavičky \texttt{WWW-Authenticate}, která zde má hodnotu \emph{Basic realm = ``Private Email Account''}. Tato položka nám říká, že autorizace je možná autorizační metodou \texttt{Basic} (neplést s~HTTP metodou). Položka \emph{realm} nám dává informace o~důvodu přihlášení. Při autorizaci \texttt{Basic} se jedná čistě o~informativní sdělení, můžeme ho tedy s~klidem ignorovat. Zajímavostí může být, že moderní webové prohlížeče jako Opera, Firefox nebo Internet Explorer tuto informaci zobrazují ve svém autorizačním dialogu \begin{figure}[ht] \centerline{\includegraphics[height=70mm]{images/opera_authorization.png}} \caption{Autorizační dialog v~prohlížeči Opera.} \end{figure} Jak tedy postupovat dál, když dostaneme odpověď \texttt{401 Unauthorized}? Řešením je odeslat celý požadavek znovu, tentokrát ale s~nově vyplněnou přihlašovací informací. Ta se nachází v~položce hlavičky \texttt{Authorization}. Její hodnotu tvoří název metody autorizace (tedy \texttt{Basic}), mezera a~samotné přihlašovací údaje -- uživatelské jméno a~heslo. Ty jsou vyžadovány v~kódování \emph{base64}, kterému je věnována odbočka uvedená dále. Příklad ukazuje požadavek, ve kterém bylo použito uživatelské jméno \emph{Alibaba} a~heslo \emph{open\_sesame} (po zakódování do base64 dostaneme řetězec \emph{QWxpYmFiYTpvcGVuX3Nlc2FtZQ==}). \begin{Verbatim} GET /email HTTP/1.1 Host: www.myexample.com Accept: text/html Authorization: Basic QWxpYmFiYTpvcGVuX3Nlc2FtZQ== \end{Verbatim} Pokud jsou naše přihlašovací údaje správné, dostaneme teď již odpověď \texttt{200 OK} spolu s~HTML reprezentací webové stránky s~uživatelským rozraním našeho e-mailového účtu. V~případě, že bychom neměli oprávnění reprezentaci získat (zadali jsme špatně heslo, nebo zkoušíme hádat cizí heslo), zaslal by nám server opět odpověď s~kódem \texttt{401 Unauthorized}. Příklad ukazuje kladnou odpověď \texttt{200 OK}: \begin{Verbatim} HTTP/1.1 200 OK Content-Type: text/html Email Account ... \end{Verbatim} Webový prohlížeč při obdržení odpovědi \texttt{401 Unauthorized} zobrazí přihlašovací dialogové okno (viděli jste ho na obrázku). Poté, co vyplníme přihlašovací údaje a~potvrdíme tlačítkem OK, prohlížeč sestaví a~pošle nový požadavek. Pokud opět dostaneme \texttt{401 Unauthorized}, zobrazí znovu zmíněný dialog. V~tomto ohledu můžeme chování prohlížeče přirovnat ke konečnému automatu. \subsection{Kódování Base64} Base64 je kódování, které převádí ASCII znaky v~klasickém řetězci na hodnoty založené na jejich pořadí v~ASCII tabulce. Nejdříve pro každý znak zjistíme jeho pozici v~ASCII tabulce. Tím dostaneme čísla, které se každé vejde do 8 bitů (maximální hodnota je 256). Tato čísla, vyjádřená pomocí všech 8 bitů spojíme dohromady ve stejném pořadí, v~jakém jsou původní znaky v~řetězci. Výsledný řetězec rozsekáme na části po 6 bitech a~každé takovéto části přiřadíme hodnotu podle Base64 tabulky. Tu si můžete prohlédnout na adrese \url{http://tools.ietf.org/html/rfc1421}, je však velmi jednoduchá --- obsahuje pouze znaky A--Z, a--z, 0--9 a~znaky \texttt{+} a~\texttt{/}. Celkem tedy 64 možných výsledných hodnot, což přesně odpovídá možným kombinacím nul~a jedniček v~zmíněných 6 bitových částech. Jelikož zdaleka ne vždy jde posloupnost rozdělit beze zbytku na části po 6 bitech, poslední část je nutné vycpat nulami. Ve výsledném base64 řetězci je pak nutné pro každé dvě vycpávací nuly přidat jeden znak ``=''. \\ \\ Příklad: \\ \\ Chceme zapsat slovo ``Java'' v~kódování base64. Po nahlédnutí do ASCII tabulky zjistíme, že jednotlivá písmena mají následující pozice: \\ ``J'' --- 74 \\ ``a'' --- 97 \\ ``v'' --- 118 \\ ``a'' --- 97 \\ \\ každou z~těchto pozic vyjádříme v~bitové podobě, tedy: \\ ``J'' --- 01001010 \\ ``a'' --- 01100001 \\ ``v'' --- 01110110 \\ ``a'' --- 01100001 \\ \\ Poté, co vše slepíme dohromady, dostaneme posloupnost: \\ 01001010011000010111011001100001 \\ \\ Tuto posloupnost rozdělíme na části po 6 bitech, pro přehlednost uveďme každou tuto část také ve formě čísla v~desítkové soustavě: \\ \\ 010010 --- 18 \\ 100110 --- 38 \\ 000101 --- 5 \\ 110110 --- 54 \\ 011000 --- 24 \\ 010000 --- 16 (všimněte si vycpání čtyřmi nulami)\\ \\ \\ Nakonec převedeme na hodnoty podle Base64 tabulky: \\ 18 --- S \\ 38 --- m \\ 5 --- F \\ 54 --- 2 \\ 24 --- Y \\ 16 --- Q \\ Dostali jsme řetězec \emph{SmF2YQ}, jelikož jsme ale použili vycpání čtyřmi nulami, musíme podle pravidel přidat do výsledku dva znaky \texttt{=} (jeden znak rovná se za každé dvě nuly), konečným výsledkem je tedy řetězec \emph{SmF2YQ==}. \subsection{Autorizační údaje v~Base64} Autorizační údaje se zpravidla skládají ze dvou částí -- uživatelského jména a~hesla. Jelikož v~HTTP je pro autorizaci definována pouze jedno pole hlavičky, \texttt{Authorization}, vyvstává otázka, jak do ní zapsat uživatelské jméno a~heslo zároveň. Řešení je poměrně neintuitivní. Uživatelské jméno (na prvním místě) oddělíme od hesla (na druhém místě) znakem dvojtečky, a~až takovýto řetězec zakódujeme pomocí base64. Jméno \emph{Alibaba} s~heslem \emph{open\_sesame} tedy spojíme. Vznikne řetězec \emph{Alibaba:open\_sesame}. Ten zakódujeme do base64 a~výsledek (v~našem případě \emph{QWxpYmFiYTpvcGVuX3Nlc2FtZQ==}) uvedeme jako hodnotu pole hlavičky \texttt{Authorization}. \subsection{Base64 a~bezpečnost autorizace} Celé použití metody base64 je však poněkud nešťastné. Je třeba si uvědomit, že stejně snadno, jako řetězec zakódujeme do base64, můžeme ho i~dekódovat. Nejedná se o~nějakou šifru, pouze o~jiný formát dat, než řetězec v~UTF-8. Autorizace pomocí metody \texttt{Basic} tedy přenáší uživatelské jméno a~heslo v~podstatě v~textové podobě. To není zrovna příliš bezpečné a~vzniká otázka, co s~tím. Nejdříve je třeba uvážit, jaké jsou míry rizika spojeného s~bezpečností. Pokud například máme aplikaci rodinného fotoalba, nedá se na ni předpokládat nějaký velký útok hackerů. V~takovémto případě nám zcela postačí základní verze autorizace popsaná výše. Pokud ale aplikace manipuluje s~citlivými daty, je potřeba bezpečnost radikálně zvýšit. To může být dosaženo buď použitím protokolu HTTPS namísto HTTP (jedná se o~rozšíření HTTP o~prvky spojené s~šifrováním) --- pak jsou uživatelské údaje, byť uvedené v~base64, zašifrovány jako celek spolu s~celým požadavkem, nebo sofistikovanější alternativy k~metodě \texttt{Basic}, metodu \texttt{Digest}. Algoritmus metody \texttt{Digest} si zde uvádět nebudeme, je založený na diskrétním logaritmu a~je velmi komplikovaný. Zájemci si o~něm mohou přečíst více na \cite{HTTP Digest Wiki}. Zde jen uveďme, že výsledkem je řetězec, jejž už nejde dekódovat na původní přihlašovací jméno a~heslo. Na serveru je v~takovém případě uložena zakódována podoba přihlašovacích údajů a~ta se porovnává se zakódovanou podobou z~pole hlavičky \texttt{Authorization}. \subsection{Závěr} HTTP je velmi oblíbený protokol pro přenos dat po internetu, hlavně HTML kódu nebo stahovaných souborů jako obrázky, filmy nebo hudba ve formátu mp3. Tento protokol je bezestavový, mezi jednotlivými požadavky si nedají přenášet žádné nastavení, což může komplikovat řešení některých problémů. I~když ve specifikaci Javy EE není zmíněn, úzce souvisí s~programováním dynamických webových stránek (JSP) a~webových služeb (jak SOAP, tak RESTful webových služeb), je proto určitě dobré alespoň jeho základy ovládat. Použitá literatura:\\ \cite{HTTP Wiki} \emph{HTTP na Wikipedii}\\ \cite{HTTP RFC} \emph{Specifikace HTTP}\\ \cite{Java Server Pages} \emph{Java Server Pages}\\ \cite{Programujeme Jakarta Struts} \emph{Programujeme Jakarta Struts}\\ \cite{RESTful Web Services} \emph{RESTful Web Services}\\