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

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ů

21.11.2014 7:41 /MaReK Olšavský
Američtí uživatelé již to zjistili, když byl ve Firefoxu defaultní vyhledávač přenastaven na Yahoo, ale Google již není jediným partnerem pro vyhledávání (a financování).
Přidat komentář

20.11.2014 7:36 /MaReK Olšavský
Libby Clark sepsala, pro Linux Foundation, příběh zapojení SanDisku do vývoje F/L/OSS. SanDisk se postupně stal 7. největším přispěvatelem do vývoje Cephu.
Přidat komentář

20.11.2014 7:36 /MaReK Olšavský
Zajímá-li vás astronomie a jste nakloněni GNU/Linuxu, jinak byste asi nenavštívili náš web, měli byste si vyzkoušet čerstvé vydání Astro Linuxu (verze 3.0). Výběr software, pro distribuci založenou na Debianu, je přizpůsoben právě astronomům.
Přidat komentář

20.11.2014 7:36 /MaReK Olšavský
Vývojáři odešlí z Nokie po ukončení snah o linuxová zařízení vytvořili společnost Jolla Ltd, která vypustila do světa první mobilní telefon a teď asi přepsala rekordy crowdfundingu kampaní na výrobu tabletu se Sailfish OS, která během 3 hodin vybrala potřebnou částku.
Přidat komentář

19.11.2014 7:20 /MaReK Olšavský
WhatsApp, potažmo současný majitel Facebook, daroval US$ 1 mil do FreeBSD Foundation. Jedná se o historicky nejvyšší jednorázovou částku pro FreeBSD a nejspíše i pro svobodný software.
Přidat komentář

19.11.2014 7:20 /MaReK Olšavský
Bezplatná verze „úvodu do GNU/Linuxu“, kterou spustila Linux Foundation na stránkách edX má úspěch, zatím jím prošlo 300 000 účastníků.
Přidat komentář

19.11.2014 7:20 /MaReK Olšavský
Finské Nokii asi nikdo nemůže rozumět. Nedlouho po prodeji mobilní divize Microsoftu představila tablet N1 s Android 5.0. Chystá Nokia vlastní restart ve vývoji mobilních telefonů, teď již s majoritním mobilním OS?
Přidat komentář

18.11.2014 7:11 /MaReK Olšavský
V pátek 14. listopadu 2014 vyšlo FreeBSD 10.1, rychle následované „desktopovou verzí“ PC-BSD 10.1 a serverovým TrueOS 10.1 (viz info na PC-BSD). FreeBSD dostalo do vínku podporu UEFI, nebo možnost bootu ze ZFS.
Přidat komentář

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

> Poslední diskuze

11.11.2014 14:24 / Libor Suchý
Nekonečný while cyklus

10.11.2014 19:09 / Libor Suchý
Re: tabulka - bitovy sucet

10.11.2014 19:03 / Libor Suchý
Re: tabulka - bitovy sucet

24.10.2014 17:47 / Petr Ježek
Andreas

16.10.2014 7:56 / Leo
Sanba

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