COMPUTERWORLD
 

profil kontakt CD-ROM CW100 předplatné

archiv anketa CO VY NA TO? CW kariéra seriály
 

IDG

IDG CZ homepage
COMPUTERWORLD
PC WORLD
INTERNET4U
MEGABYTE
TESTCENTRUM
ON-LINE






COMPUTERWORLD 22/98

Předávání parametrů pomocí rozhraní CGI

Jiří Kosek ml.

CGI skripty, které jsme si ukázali v posledním dílu našeho seriálu, byly velmi jednoduché -- zejména proto, že ke své činnosti nepotřebovaly žádné informace od uživatele. To však není příliš typický příklad. Obvykle slouží CGI skripty jako rozhraní pro práci s různými databázemi. Uživatel může například zadat klíčová slova, která ho zajímají. Klíčová slova se předají CGI skriptu a ten jako svůj výsledek může vygenerovat seznam všech článků z databáze, které obsahují zadaná klíčová slova.

Z minula již víme, že parametry nejprve předá prohlížeč serveru a ten je pak pomocí rozhraní CGI předá skriptu. Nejprve se tedy podívejme na to, jak může nějaká data poslat prohlížeč serveru.

Existují 2 metody, jak přenos dat uskutečnit. První se jmenuje GET a slouží pro přenos kratších informací. Pro přenos většího množství dat pak slouží metoda POST.

Při použití metody GET se všechny předávané informace připojí jako dotaz za otazník na konec URL, které ukazuje na CGI skript. V dotazu je potřeba provést drobné úpravy: všechny mezery se nahradí znakem "+" a znaky se speciálním významem se nahradí sekvencí znaků "%xx", kde xx je hexadecimální kód znaku. Například lomítko se převede na sekvenci "%2F".

Pokud tedy chceme skriptu pokus.cgi jako parametr předat jméno "Jan Novak", můžeme použít jedno z následujících URL:

http://server/cgi-bin/pokus.cgi?Jan+Novak

http://server/cgi-bin/pokus.cgi?Jan%20Novak

V obou dvou případech jsme museli překódovat mezeru tak, aby URL tvořilo jeden dlouhý nepřerušený řetězec.

Takovéto zadávání parametrů však není pro uživatele zrovna pohodlné. Naštěstí existuje několik uživatelsky příjemnějších způsobů, jak přimět prohlížeč k vygenerování potřebného URL s parametry:

- Stránka obsahuje ve svém záhlaví tag <ISINDEX>. V tomto případě si prohlížeč od uživatele vyžádá zadání textu do vstupního pole. Obsah pole zakóduje podle všech pravidel a metodou GET jej odešle skriptu určenému pomocí <BASE HREF="URL-skriptu">.

- U obrázku, který je současně odkazem, použijeme atribut ISMAP. Takto připravený obrázek pak slouží jako klikací mapa, kterou obsluhuje server. Pokud někam do obrázku klikneme myší, odešlou se metodou GET na server souřadnice kliknutí. Na jejich základě server obvykle vrátí nějakou stránku. Dnes se tento způsob již příliš nevyužívá, protože klientské klikací mapy jsou mnohem efektivnější. I přesto malá ukázka:

<A HREF="http://www.nekde.cz/imagemap">
<IMG SRC="mapa.gif" ISMAP></A>

Pokud uživatel klikne na obrázek mapa.gif např. na souřadnicích (x,y)=(10,50), na server se odešle požadavek http://www.nekde.cz/imagemap?10,50.

- Nejpoužívanější metodou je zařazení formuláře (element FORM) na stránku. U formuláře musíme specifikovat přenosovou metodu GET pomocí atributu METHOD=GET. Formulář může obsahovat vstupní pole několika typů. Údaje zadané do těchto vstupních polí se před odesláním zakódují, přiřadí se jménu vstupního pole a navzájem se oddělí znakem "&".

Pokud chceme pro předání dat použít metodu POST, musíme na stránce opět použít formulář, ale jako metodu je třeba uvést POST. Data se kódují stejným způsobem jako v metodě GET, ale pro jejich odeslání se vytvoří zvláštní datové spojení mezi prohlížečem a serverem. To umožňuje přenášet větší objemy dat, než představuje přidání parametrů na konec URL.

Způsob zakódování údajů z formuláře si předvedeme na malé ukázce. Předpokládejme náš známý formulář z předchozích dílů:

<FORM ACTION="http://server/cgi-bin/obsluha.cgi" METHOD=GET>
Jméno: <INPUT TYPE=TEXT NAME=jmeno><BR>
Věk: <INPUT TYPE=TEXT NAME=vek><BR>
<INPUT TYPE=SUBMIT VALUE="Odeslání formuláře">
</FORM>

Pokud uživatel vyplní jako jméno "Pavel Severa" a jako věk "47", prohlížeč po stisknutí tlačítka Odeslání formuláře vygeneruje následující požadavek:

http://server/cgi-bin/obsluha.cgi?jmeno=Pavel+Severa&vek=47

Vidíme, že obsah jednotlivých polí je identifikován svým jménem a pole jsou oddělena znakem "&".

Už víme, jak může prohlížeč poslat data na server. Vraťme se tedy k otázce, jak server předá data našemu skriptu. Rozhraní CGI nám nabízí 3 možnosti:

1. Data jsou skriptu předána jako parametry na příkazové řádce. To přichází v úvahu při předávání opravdu krátké informace pomocí metody GET (klíčová slova zadaná pomocí <ISINDEX> nebo souřadnice na klikací mapě).

2. Data jsou předána v proměnné prostředí QUERY_STRING. Tento způsob je typický pro předávání dat z formuláře odeslaného metodou GET.

3. Data jsou předána na standardní vstup skriptu -- způsob typický pro předání dat z formuláře odeslaného metodou POST.

Kromě dat od uživatele, která předá server skriptu, máme k dispozici další užitečné informace uložené v proměnných prostředí (viz tabulka 1).

Tab. 1: Proměnné prostředí předávané skriptu rozhraním CGI

ProměnnáObsah

REQUEST_METHODUrčuje způsob předávání informací -- GET nebo POST

QUERY_STRINGObsahuje data přenášená metodou GET

PATH_INFOCesta, která má být zpracována skriptem; nejčastěji jde o část cesty v URL za jménem skriptu

PATH_TRANSLATEDCesta ke stejnému souboru jako PATH_INFO; v tomto případě však byla cesta přemapována podle konfigurace serveru

CONTENT_TYPEMIME typ dat zasílaných metodou POST

CONTENT_LENGTHDélka dat zasílaných metodou POST

SCRIPT_NAMEURL právě prováděného skriptu

SERVER_NAMEJméno serveru

SERVER_PORTČíslo portu

SERVER_SOFTWAREJméno a verze programu pracujícího jako WWW server

SERVER_PROTOCOLJméno a verze protokolu, kterým přišel požadavek (typicky HTTP/1.0 nebo HTTP/1.1)

GATEWAY_INTERFACEOznačení a verze použitého rozhraní ke spuštění skriptu (typicky CGI/1.1)

REMOTE_HOSTDoménová adresa počítače, z něhož přišel požadavek

REMOTE_ADDRIP adresa počítače, z něhož přišel požadavek

AUTH_TYPEZpůsob použité autorizace uživatele

REMOTE_USERV případě, že byl uživatel autorizován, obsahuje tato proměnná jeho jméno

REMOTE_IDENTInformace o identitě získaná zpětným dotazem u klienta; tuto vlastnost příliš mnoho serverů nevyužívá

Nyní už toho víme dost na to, abychom si ukázali CGI skript, jenž bude zpracovávat parametry zadané uživatelem. Použijeme náš osvědčený příklad, který hodnotí uživatele podle jeho věku. Zadání údajů umožníme uživateli výše uvedeným formulářem. Skript, který vyhodnotí údaje na formuláři, pojmenujeme obsluha.cgi.

#!/bin/sh

echo 'Content-type: text/html'

echo

echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">'

echo '<HTML>'

echo '<HEAD>'

echo '<TITLE>Obsluha formuláře</TITLE>'

echo '</HEAD>'

echo '<BODY>'

echo '<H1>Výsledek obsluhy formuláře</H1>'

eval `echo $QUERY_STRING | awk 'BEGIN{RS="&"} {printf "WWW_%s\n",$1}' `

WWW_jmeno=`echo $WWW_jmeno | tr "+" "\040"`

echo "$WWW_jmeno je"

if [ $WWW_vek -lt 10 ]; then

echo 'pěknej mlíčnák'

elif [ $WWW_vek -lt 20 ]; then

echo 'teenager'

elif [ $WWW_vek -lt 60 ]; then

echo 'v nejlepších letech'

elif [ $WWW_vek -lt 100 ]; then

echo 'je pravděpodobně prarodič'

else

echo 'je někde mezi stovkou a smrtí'

echo '</BODY>'

echo '</HTML>'

CGI skript jsme opět zapsali v příkazovém interpretu sh. Předem upozorňuji, že po vyzkoušení skriptu je nejlepší jej ihned smazat. Náš skript totiž není zdaleka bezpečný, jak si za chvíli ukážeme.

Podívejme se nyní na skript trošku podrobněji. První řádek obsahuje určení interpretu, který se na skript použije. Dále pak generujeme HTTP hlavičku a kostru HTML stránky.

Dva řádky na začátku těla stránky jsou opravdu magické. První z nich pro každé pole formuláře, jehož hodnota je předána v proměnné QUERY_STRING, vytvoří proměnnou WWW_jméno-pole s obsahem příslušného pole. To nám usnadní další práci s předanými parametry. Druhý řádek v proměnné WWW_jmeno (ta nese obsah vstupního pole jmeno) nahradí všechny výskyty znaku "+" mezerou (ASCII kód 40 v osmičkové soustavě).

Podmínka [ $WWW_vek -lt n ] je splněna, pokud je proměnná $WWW_vek menší než n. Několik vnořených podmínek zajistí vytištění příslušného komentáře podle věku uživatele.

Vidíme, že tvorba skriptů cestou příkazového interpretu je určena spíše pro unixového specialistu, nežli pro "normálního člověka".

Bezpečnost a CGI skripty

Pro psaní CGI skriptů se nejčastěji používají interpretované jazyky jako Bourne shell (sh) nebo Perl. To však přináší velká bezpečnostní rizika. Ukážeme si zde bezpečnostní díru v našem skriptu.

Pokud někdo bude chtít náš skript zneužít pro zjištění důležitých informací o systému, může využít některé méně známé vlastnosti interpretu sh. Mezi ně patří i to, že na jedné řádce lze příkazy oddělovat pomocí středníku -- to má význam, pokud např. nějaký "chytrák" zavolá náš skript pomocí následujícího URL:

http://server/cgi-bin/obsluha.cgi?;who

Následkem tohoto příkazu dojde v CGI skriptu k expanzi příkazu echo $QUERY_STRING na echo ;who. Výsledkem je, že na výstup skriptu se zapíše prázdná řádka (příkaz echo) a výsledek programu who. Zcela kdokoliv tak může zjistit, kdo v danou chvíli pracuje na serveru. Místo příkazu who můžeme použít libovolný jiný příkaz -- např. následující URL:

http://server/cgi-bin/obsluha.cgi?;cat</etc/passwd

Vrátí se nám stránka, která na svém začátku bude obsahovat výpis informací o všech uživatelích systému. Z tohoto výpisu lze zjistit uživatele, kteří heslo nemají nastaveno, a u těch ostatních lze poměrně snadno jejich heslo rozšifrovat. Kdokoliv se pak pomocí protokolu Telnet může připojit na server a provádět tam téměř cokoliv.

Pokud tedy chceme vytvářet bezpečné skripty v interpretovaných jazycích, musíme vždy příchozí data zkontrolovat a před jejich zpracováním z nich eliminovat všechny nebezpečné znaky (jako je středník).

Ošetřit všechny nebezpečné kombinace vstupních parametrů není však vůbec jednoduché a je celkem pravděpodobné, že na nějakou možnost zapomeneme. Je proto lepší CGI skripty psát v jazycích, ve kterých je nutno program před spuštěním přeložit do spustitelné formy. V těchto jazycích (C, C++, Java apod.) je pak výše zmíněné nebezpečí obelstění skriptu do značné míry eliminováno.

Viděli jsme, že CGI skripty jsou jako oheň -- dobrý sluha, ale špatný pán. V seriálu se budeme příště zabývat především skriptovacími jazyky, které se vkládají přímo do HTML stránky, jako je PHP a ASP. Práce s nimi je jednodušší a většinou i efektivnější. Pro speciální aplikace však může být výhodné použít CGI skripty -- a nyní již znáte princip jejich práce a způsob předávání parametrů.

V příštích pokračováních seriálu se podíváme na různé druhy vstupních polí, které lze používat ve webovských formulářích.

 

 

© IDG Czechoslovakia, a.s., Všechna práva vyhrazena
info@idg.cz, webmaster@idg.cz