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 7122×

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ů

23.10.2014 7:13 /MaReK Olšavský
CERN používá OpenStack přibližně rok. Jaké je aktuální používání při výzkumu ukazuje článek na OpenSource.com. Vyprodukovaných dat, z měření, není malé množství a pro jejich zpracování je potřebný výkon několikatisíců serverů a pracovních stanic.
Přidat komentář

23.10.2014 7:13 /MaReK Olšavský
Prodejce starších her; jež jsou často hratelnější, než moderní grafické orgie; Good Old Games dosáhl milníku 100 her připravených pro Linux (nejde o portace, ale připravené konfigurace DOSBoxu/Wine).
Přidat komentář

23.10.2014 7:13 /MaReK Olšavský
O malou reklamu pro Ubuntu se postaral Andy Swan, se svým laptopem, při analýze počasí pro tragickou Velkou Cenu Japonska 2014 (Formule 1).
Přidat komentář

22.10.2014 7:19 /MaReK Olšavský
Programovacímu jazyku Swift, jenž nedávno zveřejnil Apple a je uzavřený, vzniká svobodná odpověď Phoenix (repozitář). Jazyk bude stejný, takže lze očekávat, že se Apple bude bránit i soudně. Název Phoenix už nejspíše také někdo používá, starší pamatují, že se tak chvíli jmenoval dnešní Mozilla Firefox.
Přidat komentář

22.10.2014 7:19 /MaReK Olšavský
Programátorům v PHP je určen nástroj RIPS, který jim pomůže odhalit zranitelnosti v jejich kódu. Pokud znáte další nástroje, podělte se o ně v diskusi.
Přidat komentář

22.10.2014 7:18 /MaReK Olšavský
HDMI sticků, které povyšují možnosti TV, je na trhu nepřeberné množství, ale Apec Electronics se nepokouší zaujmout nejlevnější cenou. Za US$ 110 dostanete Android běžící na 4 jádrovém Atomu (takže platformu x86), přičemž místo Androidu lze pořídit verzi s MS Windows 8.1.
Přidat komentář

21.10.2014 7:34 /MaReK Olšavský
Ačkoliv je Debian poměrně konzervativní distribucí, je kolem něj živo. Vedle vydání Debianu 7.7 může zaujmout skupina vývojářů, kteří chystají další fork Debianu, jenž chtějí „osadit“ systemd, namísto stávajícího sysvinit.
Přidat komentář

21.10.2014 7:17 /MaReK Olšavský
OpenBSD se, nedlouho před vydáním další finální verze, dostalo k významnému milníku, 300 000. commitu v repozitářích.
Přidat komentář

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

> Poslední diskuze

16.10.2014 7:56 / Leo
Sanba

13.10.2014 7:20 / MaReK Olšavský
Re: PDF a podpis

10.10.2014 8:01 / Hynek Beran
PDF a podpis

10.10.2014 7:41 / Dusan Hlavac
Re: Takže nic.

10.10.2014 6:36 / MaReK Olšavský
Re: Může, ale nemusí

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