LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Perl (83) - CGI - získávání dat od uživatele

Perl Konečně se dostáváme ke kapitole, která popisuje získávání dat od klienta. Vstup je jedno z důležitých témat webového programování.

13.7.2009 00:00 | Jiří Václavík | Články autora | přečteno 6870×

Co to vstup dat do CGI skriptu vlastně je? Nejprve uveďme, jakou má vstup formu. Můžeme říct, že to je datová struktura podobná hashi. Uživatel pošle serveru dvojice klíč - hodnota. Tyto informace jsou pak s předány CGI skriptu běhěm volání.

Jsou dvě metody, jak může uživatel předávat serveru vstup. Buď pomocí formulářů (metoda POST) nebo je může zakomponovat do URL adresy požadovaného dokumentu. Oběma se budeme postupně zabývat.

Možná je vždy pouze jedna metoda vstupu. Nelze tedy zároveň přijímat zároveň jak formulářová data, tak data z URL. Abychom mohli ve sporných případech určit, který vstup je aktuální, získá CGI skript od serveru proměnnou prostředí REQUEST_HETHOD, ke které v Perlu přistupujeme pomocí $ENV{"REQUEST_METHOD"}. Metodu vstupu indikuje obsah této proměnné, což je buď řetězec POST nebo GET.

Vstup z formulářů

Data získaná z formulářů čteme ze standardního vstupu. Konkrétně, máme-li například formulář se dvěma položkami jmeno a heslo, přečteme ze standardního vstupu řetězec, do kterého budou zakódované položky jmeno a heslo i s hodnotami, které uživatel do formuláře zadal.

Formát vstupního řetězce má obecně tvar klíč1=hodnota1&klíč2=hodnota2&...&klíčn=hodnotan. To znamená, že pro situaci s položkami jmeno a heslo by vypadal získaný řetězec takto: jmeno=jiri&heslo=m0je_hEslo.

Pokud má nějaký parametr vstupního řetězce jako hodnotu seznam, je pro všechny hodnoty tohoto seznamu vytvořena dvojice klíč-hodnota se stejným klíčem. Příkladem může být řetězec check=a&check=b&check=c.

Vstup z URL

Druhou zmiňovanou možností vstupu je získání řetězce zakomponovaného do URL adresy dokumentu. Předání metodou GET spočívá v tom, že za umístění dokumentu zadáme otazník a dále dvojice ve formátu klíč=hodnota oddělené znakem & (ampérsand).

To znamená, že pokud zadáme do WWW prohlížeče jako umístění adresu http://localhost/cgi-bin/skript.cgi?jmeno=jiri&heslo=m0je_hEslo (mimochodem, nešifrované heslo v příkazovém řádku prohlížeče není příliš bezpečné), dostane CGI skript parametry jmeno a heslo metodou GET.

Získaný řetězec parametrů - tedy vše, co je v URL za otazníkem - se nám objeví v proměnné prostředí QUERY_STRING. V CGI skriptu tak můžeme k těmto datům přistupovat z proměnné $ENV{"QUERY_STRING"}.

Dále již postupujeme stejně jako u formulářového vstupu.

Zpracování získaných řetězců

Teď už by neměl být problém pomocí nám dobře známých nástrojů Perlu získat z řetězce hash parametrů. Máme zde dvě drobně překážky.

  1. Rozdělením řetězců spojených znakem & získáme řetězce ve formátu klíč=hodnota. Tyto řetězce na pozici rovnítka opět rozdělíme a získáme tak hash parametrů.
  2. Aby bylo možné přenášet v URL i písmena s háčky a čárkami a také mezery, probíhá již u klienta (ve WWW prohlížeči) konverze těchto znaků. Zkusíme-li zadat do formuláře písmena s háčky, CGI skript je dostane zakódované. Místo slova zpět tak dostaneme zp%ECt. Musíme tak ještě před definitivním uložením do hashe nahradit sekvenci %.. za správný znak. Mezery jsou nahrazovány znakem +.
my %hash;
for (split "&", $retezec){
    my($k, $h) = split "=";
    $h =~ tr/+/ /;
    $h =~ s/%(..)/chr hex $1/ge;
    $hash{$k} = $h;
}

Nyní máme v proměnné %hash požadované páry parametr-hodnota, se kterými můžeme pohodlně pracovat.

Poznámka - Úplně jsme vynechali parametry se seznamovou hodnotou. Prozatím se jim nebudeme věnovat.

Konkrétní příklad obsluhy formulářů

Jedno z nejčastějších užití CGI je zpracovávání dat, které uživatel zadal do formuláře. Na základě těchto dat mohou být například přidány záznamy do databáze nebo můžeme naopak z databáze požadovaná data získat.

Již víme, jak získat formulářová data. Máme tedy všechny potřebné znalosti k tomu, abychom si uvedli první ukázku programu, jež bude vstupu od uživatele využívat.

Vytvoříme si přihlašovací skript, který na se základě do formuláře zadaného uživatelského jména a hesla otáže databáze, zda takový uživatel se zadaným heslem existuje. Pokud zjistí, že tento uživatel skutečně existuje, zobrazíme z databáze zprávu. V opačném případě přesměrujeme na stránku, která vygeneruje chybu.

Ze všeho nejdříve bude třeba navrhnout datovou základnu. Otevřeme tedy řádkového databázového klienta, vytvoříme databázi s názvem projekt a zde umístíme tabulku users s následující strukturou. vložíme také jeden testovací záznam.

create table users (
    id int not null primary key auto_increment,
    username varchar(60) not null,
    md5passwd varchar(32) not null,
    zprava varchar(255) not null
);
insert into users (user, md5passwd, zprava) values ('pokus', 'fde27fdce626407e9ad040b7bb017882', 'TAJNA ZPRAVA');

Toto je zdrojový text pro databázový systém MySQL. Chcete-li použít například Postgres, pak místo druhého řádku napište id serial primary key,.

Další poznámka bude směřovat k uložení hesla. Do databáze neukládáme čisté heslo (pokus), ale jeho md5-hashovanou verzi. Použití hashovacího algoritmu nám zaručí, že i kdyby se potenciální útočník dostal do databáze, získá pouze data, ale nikoliv hesla. My heslo nepotřebujeme, protože budeme porovnávat pouze výsledek funkce md5.

Je třeba dodat, v roce 2004 byly nalezeny první kolize algoritmu md5 (to jest více řetězců se stejným hashem) a nyní je již možné provádět inverzní operaci k hashování na běžném počítači do několika sekund. Pro bezpečnější uložení hesel lze použít některý z rodiny algoritmů SHA-2, u kterých ještě žádná kolize objevena nebyla.

Nyní musíme vytvořit dva soubory. Prvním z nich bude obyčejný HTML formulář, který bude data odesílat CGI skriptu, což bude druhý soubor.

Soubor s formulářem je čisté HTML bez jakýchkoliv dynamických prvků. Dále budeme pracovat s níže uvedeným formulářem. Uložíme ho například jako formular.html do kořenového adresáře Apache. Fyzicky tedy bude ležet v /usr/local/apache2/htdocs a do prohlížeče budeme zadávat http://localhost/formular.html.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Log in</title>
</head>
<body>

<form action="/cgi-bin/login.cgi" method='POST'>
    Uživatelské jméno: <input type='text' name='username'><br>
    Heslo: <input type='text' name='heslo'><br>
    <input type='submit' name='akce' value='Log in'>
</form>

</body>
</html>

Dále vytvoříme samotný CGI skript, který bude formulář obsluhovat. Jak vidíme z výše uvedeného HTML kódu, jako umístění CGI skriptu jsme zvolili /usr/local/apache2/cgi-bin/login.cgi.

Úvod skriptu login.cgi je obvyklý. Protože již víme, že budeme používat databázi, importujeme hned i modul DBI. Dále vytvoříme hash parametrů a budeme načítat data.

#!/usr/bin/perl
use strict;
use DBI;

#do proměnné %hash uložíme formulářová data
my %hash;
for (split "&", <STDIN>){
    my($k, $h) = split "=";
    $h =~ tr/+/ /;
    $h =~ s/%(..)/chr hex $1/ge;
    $hash{$k} = $h;
}

Nyní se musíme dotázat databáze na správnost uživatelem zadaných údajů. Podle tohoto kritéria se bude odvíjet tělo generovaného dokumentu. Musíme ošetřit případy selhání pokusu o připojení k databázi a nekorektní zadání údajů. Podle toho, kterou větví se bude program ubírat, uložíme do proměnné $telo tělo dokumentu. Na závěr celý dokument vytiskneme.

Nejdříve se tedy musíme pokusit navázat spojení s databází. Je-li toto spojení neúspěšné, přesměrujeme na CGI skript k tomu určený.

my $telo;
my $dbh = DBI->connect("dbi:mysql:dbname=projekt", "user", "");
if(!$dbh){
    print "Location: error.cgi?cislo_chyby=1\n\n";
}else{
    #sem se program dostane, bude-li navázání spojení k databázi úspěšné
}
$dbh->disconnect;

Nyní již předpokládáme, že jsme se úspěšně spojili s databází. Dále se musíme zamyslet nad dotazem, který jí položíme. Potřebujeme zjistit hashované heslo a zprávu. Budeme předpokládat, že existuje vždy jeden uživatel stejného jména nehledě na velikost písmen.

    my $q = $dbh->prepare("SELECT md5passwd, zprava FROM users WHERE UPPER(username)=UPPER(?)");
    $q->execute($hash{"username"});

Aktuální otázka teď zní, zda vůbec zadaný uživatel existuje. To zjistíme podle toho, jestli nám databáze na dotaz pošle nějaké výsledky. Pokud ne, uživatel zadal neplatné uživatelské jméno.

    if(my($md5passwd, $zprava) = $q->fetchrow_array){
        #sem se program dostane, pokud zadané uživatelské jméno je v databázi
    }else{
        $telo = "<h1>Uživatel neexistuje<h1>"
    }

Zbývá ná zkontrolovat poslední věc, kterou je heslo. Tady nastává drobný problém, nebo v databázi máme heslo hashované pomocí md5 a heslo zadané je nešifrované. Jak je porovnat?

V podstatě jedinou možností, kterou máme, je zašifrovat zadané heslo a porovnat vzniklé md5 hashe. Perl má tu výhodu, že existuje archiv modulů CPAN, kde si snadno dohledáme modul Digest::MD5. Pro hexadecimální podobu md5 šifry si do CGI skriptu importujeme funkci md5_hex. Kdyby někdo chtěl použít zmíněný bezpečnější algoritmus, použije modul Digest::SHA2.

use Digest::MD5 qw(md5_hex);

Teď již není nic jednoduššího, než porovnat oba md5 hashe a v případě shody uložit zprávu o úspěchu nebo v opačném případě o neúspěchu.

        if(md5_hex($hash{"heslo"}) eq $md5passwd){
            $telo = "<h1>Úspěch!<h1>\n$zprava";
        }else{
            $telo = "<h1>Nesedí heslo<h1>";
        }

Na závěr vytiskneme HTML dokument.

print << "HTML";
Content-type: text/html; Charset="iso-8859-2"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
    <TITLE>Výsledek</TITLE>
</HEAD>
<BODY>
<font color="#800000">$telo</font>
</BODY>
</HTML>
HTML

Je dobré si uvědomit, jak je to s ošetřováním nakažených dat. Zde k problémům nedošlo.

Pokud si chcete tuto miniaplikaci také vyzkoušet, stahujte zde.

Příklad pro vstup metdodou GET

Abychom si mohli ukázat v praxi, jak pracovat s metodou GET, nechali jsme si v předchozí ukázce CGI skriptu přesměrování v případě chyby databáze. Je-li databáze nedostupná, volá se error.cgi?cislo_chyby=1. Zde je ukázka poněkud jednoduché, leč názorné implementace skriptu error.cgi.

#!/usr/bin/perl
use strict;

my $cislo_chyby = $ENV{"QUERY_STRING"} =~ /cislo_chyby=(\d*)/;
my $chyba;

if   ($cislo_chyby == 1){$chyba = "Chyba při práci s databází";}
elsif($cislo_chyby == 2){$chyba = "Jiná chyba";}
else{                    $chyba = "Neidentifikovaná chyba";}

print << "HTML";
Content-type: text/html; Charset="iso-8859-2"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
    <TITLE>Výsledek</TITLE>
</HEAD>
<BODY>
<h1>$chyba</h1>
</BODY>
</HTML>
HTML

Verze pro tisk

pridej.cz

 

DISKUZE

Zadani hesla s echem? 14.7.2009 14:20 Roman Vašíček




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

22.8.2014 7:15 /MaReK Olšavský
Google chce Chromebooky (různých výrobců) prosadit i v enterprise sféře, proto začal spolupracovat s Citrixem. Citrix, jakožto leader terminálových řešení, může Google pomoci prosadit se v segmentu, který je více výdělečný, než retailový trh.
Přidat komentář

22.8.2014 7:15 /MaReK Olšavský
Canonical spojil síly s The Khronos Group, aby pomohl s vývojem pro nástupce X Window serveru. Vývoj OpenGL implementace tím získává cenné posily.
Přidat komentář

21.8.2014 7:09 /MaReK Olšavský
Mezi významné uživatele GNU/Linuxu patří i Evropská Vesmírná Agentura (ESA), která používá 390 serverů se SLES, ale openSUSE je zde „doma“ už delší dobu.
Přidat komentář

20.8.2014 7:02 /MaReK Olšavský
Lehký úvod pro nasazení Dockeru přinesl web Opensource.com. Autor vysvětlil nejen první kroky v nasazení Dockeru, ale i filosofii kontejnerů.
Přidat komentář

20.8.2014 7:02 /MaReK Olšavský
AMD se snaží konkurovat Intelu i na poli SSD disků, ohlásila Radeon R7 Series SSD (oznaření Radeon může mást, tentokrát nejde o GPU). SSD obsahuje MLC NAND čipy Toshiba A19, s kontrolerem Barefoot 3 M00 a základní verze (120 GB) se prodává za US$ 100.
Přidat komentář

19.8.2014 16:39 /Miloslav Ponkrác

C++ schválilo standard C++14.. Ještě je třeba dokončit editační práce na finální verzi dokumentů standardu.

Takže C++ bude mít velmi brzy 3 základní standardy: ISO C++98/03, ISO C++11 a ISO C++14. Všechny novější standardy jsou vzájemně výborně zpětně kompatibilní se staršími (až ne velice nepodstatné drobnosti), takže C++ programátor je může vnímat pouze jako vzájemné rozšiřování.


Přidat komentář

19.8.2014 7:53 /MaReK Olšavský
Rusko to evidentně myslí s odklonem od velkých dodavatelů software vážně. Přechod začalo ministerstvo zdravotnictví, jež nahrazuje produkty Microsoftu a Oracle řešeními na bázi GNU/Linuxu a PostgreSQL,
Přidat komentář

19.8.2014 7:53 /MaReK Olšavský
Nostalgie za původním vzhledem a chováním desktopu GNOME, které bylo uživatelsky mnohem lepší, vedla k vytvoření nového desktopu MATE. Ubuntu, jakožto nejpopulárnější distribuce a původně i „vlajková loď“ GNOME, má i fork s MATE, jenž se stane oficiální větví, čímž se zařadí po bok Kubuntu, Xubuntu a Lubuntu.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

19.8.2014 11:02 / Le-Ze
Python s Lighttpd

15.8.2014 3:12 / Miloslav Ponkrác
Re: Kdyby autoři BeoSu nebyli blbci

15.8.2014 3:01 / Miloslav Ponkrác
Re: WIFI ůprava paketů připojených zařízení

15.8.2014 2:56 / Miloslav Ponkrác
Re: Linus tedy střílí do unixové architektury

13.8.2014 18:58 / Aleš Hakl
Re: Linus tedy střílí do unixové architektury

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2014) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze | zákony online