Rozhraní Common Gateway - Common Gateway Interface

V oblasti výpočetní techniky je Common Gateway Interface ( CGI ) specifikací rozhraní, která umožňuje webovým serverům spouštět externí program, obvykle zpracovávat požadavky uživatelů.

Takové programy jsou často psány ve skriptovacím jazyce a běžně se označují jako CGI skripty , ale mohou zahrnovat kompilované programy.

Typický případ použití nastane, když webový uživatel odešle webový formulář na webovou stránku, která používá CGI. Data formuláře jsou odeslána na webový server v rámci požadavku HTTP s adresou URL označující skript CGI. Webový server poté spustí skript CGI v novém počítačovém procesu a předá mu data formuláře. Výstup skriptu CGI, obvykle ve formě HTML , skript vrátí na webový server a server jej předá zpět do prohlížeče jako odpověď na požadavek prohlížeče.

Vyvinutý na počátku 90. let minulého století, CGI byl nejstarší dostupnou dostupnou metodou, která umožňovala interaktivní webovou stránku. Přestože je CGI stále používán, je ve srovnání s novějšími technologiemi relativně neefektivní a byl do značné míry nahrazen.

Dějiny

Oficiální logo CGI z oznámení specifikace

V roce 1993 tým Národního centra pro superpočítačové aplikace (NCSA) zapsal specifikaci pro volání spustitelných souborů příkazového řádku na mailing list www-talk. Ostatní vývojáři webových serverů jej přijali a od té doby je standardem pro webové servery. Pracovní skupina, které předsedal Ken Coar, byla zahájena v listopadu 1997 s cílem formálněji definovat definici CGI podle NCSA. Výsledkem této práce je RFC 3875, který specifikoval CGI verze 1.1. V RFC jsou konkrétně uvedeni tito přispěvatelé:

Historicky byly CGI skripty často psány pomocí jazyka C. RFC 3875 "The Common Gateway Interface (CGI)" částečně definuje CGI pomocí C, říká, že k proměnným prostředí "přistupuje rutina knihovny C getenv () nebo proměnné prostředí".

Název CGI pochází z počátků webu, kdy weboví mistři chtěli propojit starší informační systémy, jako jsou databáze, se svými webovými servery. Program CGI byl spuštěn serverem, který poskytoval společnou „bránu“ mezi webovým serverem a starším informačním systémem.

Účel specifikace CGI

Na každém webovém serveru je spuštěn serverový software HTTP , který reaguje na požadavky webových prohlížečů . Server HTTP má obecně adresář (složku) , který je určen jako kolekce dokumentů - soubory, které lze odesílat do webových prohlížečů připojených k tomuto serveru. Pokud má například webový server název domény example.coma jeho sbírka dokumentů je uložena /usr/local/apache/htdocs/v místním systému souborů, webový server odpoví na požadavek http://example.com/index.htmlodesláním (předem napsaného) souboru do prohlížeče /usr/local/apache/htdocs/index.html.

U stránek vytvořených za běhu může serverový software odložit požadavky na oddělené programy a předat výsledky žádajícímu klientovi (obvykle jde o webový prohlížeč, který stránku zobrazuje koncovému uživateli). V počátcích internetu byly takové programy obvykle malé a psané skriptovacím jazykem; proto byli známí jako skripty .

Takové programy obvykle vyžadují, aby v žádosti byly uvedeny další informace. Pokud by byla například Wikipedie implementována jako skript, jedna věc, kterou by skript potřeboval vědět, je, zda je uživatel přihlášen, a pokud je přihlášen, pod jakým jménem. Na těchto informacích závisí obsah v horní části stránky Wikipedie.

HTTP poskytuje prohlížečům způsoby, jak tyto informace předávat webovému serveru, např. Jako součást adresy URL. Serverový software pak musí tyto informace nějakým způsobem předat skriptu.

Naopak po návratu musí skript poskytnout všechny informace požadované HTTP pro odpověď na požadavek: stav HTTP požadavku, obsah dokumentu (je -li k dispozici), typ dokumentu (např. HTML, PDF nebo prostý text) a tak dále.

Zpočátku by jiný serverový software používal různé způsoby k výměně těchto informací se skripty. V důsledku toho nebylo možné psát skripty, které by fungovaly bez úpravy pro jiný serverový software, přestože vyměňované informace byly stejné. Proto bylo rozhodnuto specifikovat způsob výměny těchto informací: CGI ( Common Gateway Interface , protože definuje běžný způsob, jakým může serverový software komunikovat se skripty). Programy generující webové stránky vyvolávané serverovým softwarem, které fungují podle specifikace CGI, se nazývají skripty CGI .

Tato specifikace byla rychle přijata a je stále podporována všemi známými serverovými softwary, jako jsou Apache , IIS a (s příponou) servery založené na node.js.

Rané použití skriptů CGI bylo zpracování formulářů. Na začátku HTML měly formuláře HTML obvykle atribut „akce“ a tlačítko označené jako tlačítko „Odeslat“. Po stisknutí tlačítka Odeslat bude identifikátor URI zadaný v atributu „akce“ odeslán na server s údaji z formuláře odeslaného jako řetězec dotazu . Pokud „akce“ určuje skript CGI, spustí se skript CGI a poté vytvoří stránku HTML.

Pomocí CGI skriptů

Webový server umožňuje svému majiteli konfigurovat, které adresy URL budou zpracovávat které skripty CGI.

To se obvykle provádí tak, že nový adresář v kolekci dokumentů označíte jako obsahující skripty CGI - jeho název je často cgi-bin. Může být například /usr/local/apache/htdocs/cgi-binoznačen jako adresář CGI na webovém serveru. Když webový prohlížeč požaduje adresu URL, která ukazuje na soubor v adresáři CGI (např. http://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query=string), /usr/local/apache/htdocs/cgi-bin/printenv.plServer HTTP namísto jednoduchého odeslání tohoto souboru ( ) do webového prohlížeče spustí zadaný skript a předá výstup skriptu do webového prohlížeče. To znamená, že cokoli, co skript odešle na standardní výstup, je předáno webovému klientovi, místo aby se zobrazovalo na obrazovce v okně terminálu.

Jak bylo uvedeno výše, specifikace CGI definuje, jak jsou do skriptu předávány další informace předané s požadavkem. Pokud je například k adrese URL připojeno lomítko a další názvy adresářů bezprostředně za názvem skriptu (v tomto případě /with/additional/path), pak je tato cesta uložena v PATH_INFO proměnné prostředí před voláním skriptu. Pokud jsou parametry odeslány do skriptu prostřednictvím požadavku HTTP GET (otazník připojený k adrese URL, následovaný páry param = hodnota; v příkladu ?and=a&query=string), pak jsou tyto parametry uloženy v QUERY_STRINGproměnné prostředí před voláním skriptu. Pokud jsou parametry odeslány do skriptu prostřednictvím požadavku HTTP POST , jsou předány standardnímu vstupu skriptu . Skript pak může číst tyto proměnné prostředí nebo data ze standardního vstupu a přizpůsobit se požadavku webového prohlížeče.

Příklad

Následující program Perl zobrazuje všechny proměnné prostředí předávané webovým serverem:

#!/usr/bin/env perl

=head1 DESCRIPTION

printenv — a CGI program that just prints its environment

=cut
print "Content-Type: text/plain\n\n";

for my $var ( sort keys %ENV ) {
    printf "%s=\"%s\"\n", $var, $ENV{$var};
}

Pokud webový prohlížeč vydá požadavek na proměnné prostředí na http://example.com/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with%20percent%20encoding, 64bitový webový server Windows 7 se spuštěným cygwin vrátí následující informace:

COMSPEC="C:\Windows\system32\cmd.exe"
DOCUMENT_ROOT="C:/Program Files (x86)/Apache Software Foundation/Apache2.4/htdocs"
GATEWAY_INTERFACE="CGI/1.1"
HOME="/home/SYSTEM"
HTTP_ACCEPT="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
HTTP_ACCEPT_CHARSET="ISO-8859-1,utf-8;q=0.7,*;q=0.7"
HTTP_ACCEPT_ENCODING="gzip, deflate, br"
HTTP_ACCEPT_LANGUAGE="en-us,en;q=0.5"
HTTP_CONNECTION="keep-alive"
HTTP_HOST="example.com"
HTTP_USER_AGENT="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:67.0) Gecko/20100101 Firefox/67.0"
PATH="/home/SYSTEM/bin:/bin:/cygdrive/c/progra~2/php:/cygdrive/c/windows/system32:..."
PATHEXT=".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC"
PATH_INFO="/foo/bar"
PATH_TRANSLATED="C:\Program Files (x86)\Apache Software Foundation\Apache2.4\htdocs\foo\bar"
QUERY_STRING="var1=value1&var2=with%20percent%20encoding"
REMOTE_ADDR="127.0.0.1"
REMOTE_PORT="63555"
REQUEST_METHOD="GET"
REQUEST_URI="/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with%20percent%20encoding"
SCRIPT_FILENAME="C:/Program Files (x86)/Apache Software Foundation/Apache2.4/cgi-bin/printenv.pl"
SCRIPT_NAME="/cgi-bin/printenv.pl"
SERVER_ADDR="127.0.0.1"
SERVER_ADMIN="(server admin's email address)"
SERVER_NAME="127.0.0.1"
SERVER_PORT="80"
SERVER_PROTOCOL="HTTP/1.1"
SERVER_SIGNATURE=""
SERVER_SOFTWARE="Apache/2.4.39 (Win32) PHP/7.3.7"
SYSTEMROOT="C:\Windows"
TERM="cygwin"
WINDIR="C:\Windows"

Některé, ale ne všechny z těchto proměnných jsou definovány standardem CGI. Některé z nich, jako je PATH_INFO, QUERY_STRINGa ty začínající HTTP_, předávání informací spolu z požadavku HTTP.

Z prostředí je vidět, že webovým prohlížečem je Firefox běžící na počítači se systémem Windows 7 , webovým serverem je Apache běžící na systému, který emuluje Unix , a je pojmenován skript CGI cgi-bin/printenv.pl.

Program pak mohl vygenerovat jakýkoli obsah, zapsat jej na standardní výstup a webový server jej přenese do prohlížeče.

Níže jsou uvedeny proměnné prostředí předávané programům CGI:

  • Proměnné specifické pro server:
  • Vyžádejte si konkrétní proměnné:
    • SERVER_PROTOCOL: HTTP/ verze .
    • SERVER_PORT: TCP port (desetinný).
    • REQUEST_METHOD: název metody HTTP (viz výše).
    • PATH_INFO: přípona cesty, pokud je připojena k URL za názvem programu a lomítkem.
    • PATH_TRANSLATED: odpovídající úplná cesta podle očekávání serveru, pokud PATH_INFOje k dispozici.
    • SCRIPT_NAME: relativní cesta k programu, jako /cgi-bin/script.cgi.
    • QUERY_STRING: část URL po ? charakter. Řetězec dotazu může být složen z * jména = hodnota páry odděleny ampersandy (jako var1 = hodnota1 & var2 = hodnota2 ...), jsou-li použity k předložení formuláře data přenesena pomocí metody GET definované HTML aplikace / x-www-form -kódované .
    • REMOTE_HOST: název hostitele klienta, nenastaveno, pokud server takové vyhledávání neprovedl.
    • REMOTE_ADDR: IP adresa klienta (desetinná tečka).
    • AUTH_TYPE: identifikační typ, pokud existuje.
    • REMOTE_USERpoužívá se pro určité AUTH_TYPEs.
    • REMOTE_IDENT: viz ident , pouze pokud server takové vyhledávání provedl.
    • CONTENT_TYPE: Typ vstupních dat pro internetová média, pokud je použita metoda PUT nebo POST, poskytovaná prostřednictvím hlavičky HTTP.
    • CONTENT_LENGTH: obdobně velikost vstupních dat (desítková, v oktetech ), pokud jsou poskytována prostřednictvím hlavičky HTTP.
    • Proměnné uplynula uživatelského agenta ( HTTP_ACCEPT, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT, HTTP_COOKIEa možná i další) obsahují hodnoty odpovídající HTTP hlavičky , a proto mají stejný smysl.

Program vrátí výsledek na webový server ve formě standardního výstupu, počínaje záhlavím a prázdným řádkem .

Záhlaví je kódováno stejným způsobem jako záhlaví HTTP a musí obsahovat typ MIME vráceného dokumentu. Záhlaví, doplněná webovým serverem, jsou obecně předávána s odpovědí zpět uživateli.

Zde je jednoduchý program CGI napsaný v Pythonu 3 spolu s HTML, který zpracovává jednoduchý problém s přidáváním.

add.html:

<!DOCTYPE html>
<html>
 <body>
  <form action="add.cgi" method="POST">
   <fieldset>
     <legend>Enter two numbers to add</legend>
     <label>First Number: <input type="number" name="num1"></label><br/>
     <label>Second Number: <input type="number" name="num2"></label><br/>
   </fieldset>
   <button>Add</button>
  </form>
 </body>
</html>

add.cgi:

#!/usr/bin/env python3

import cgi, cgitb
cgitb.enable()

input_data = cgi.FieldStorage()

print('Content-Type: text/html') # HTML is following
print('')                         # Leave a blank line
print('<h1>Addition Results</h1>')
try:
    num1 = int(input_data["num1"].value)
    num2 = int(input_data["num2"].value)
except:
    print('<output>Sorry, the script cannot turn your inputs into numbers (integers).</output>')
    raise SystemExit(1)
print('<output>{0} + {1} = {2}</output>'.format(num1, num2, num1 + num2))

Tento program Python 3 CGI získává vstupy z HTML a sčítá dvě čísla dohromady.

Rozvinutí

Webový server, který podporuje CGI, lze nakonfigurovat tak, aby interpretoval adresu URL, která slouží jako odkaz na skript CGI. Běžnou zvyklostí je mít cgi-bin/ adresář na základně adresářového stromu a považovat všechny spustitelné soubory v tomto adresáři (a žádné jiné, kvůli bezpečnosti) za skripty CGI. Další populární konvencí je používání přípon souborů ; například pokud jsou skriptům CGI důsledně dána přípona .cgi, webový server lze nakonfigurovat tak, aby všechny takové soubory interpretoval jako skripty CGI. I když je to pohodlné a vyžaduje to mnoho předem zabalených skriptů, otevírá server k útoku, pokud vzdálený uživatel může nahrát spustitelný kód se správným rozšířením.

V případě HTTP PUT nebo POST jsou data odeslaná uživatelem poskytnuta programu prostřednictvím standardního vstupu . Webový server vytvoří podmnožinu předaných proměnných prostředí a přidá podrobnosti týkající se prostředí HTTP.

Využití

CGI se často používá ke zpracování vstupních informací od uživatele a produkci příslušného výstupu. Příkladem programu CGI je implementace wiki . Pokud uživatelský agent požaduje název položky, webový server spustí program CGI. Program CGI načte zdroj stránky této položky (pokud existuje), transformuje ji do HTML a vytiskne výsledek. Webový server přijímá výstup z programu CGI a přenáší jej do uživatelského agenta. Pokud pak uživatelský agent klikne na tlačítko „Upravit stránku“, program CGI naplní textareaobsah stránky HTML nebo jinou úpravou úprav. Nakonec, když uživatelský agent klikne na tlačítko „Publikovat stránku“, program CGI transformuje aktualizovaný HTML do zdroje stránky dané položky a uloží jej.

Bezpečnostní

Programy CGI se standardně spouští v kontextu zabezpečení webového serveru. Při prvním zavedení byla poskytnuta řada ukázkových skriptů s referenčními distribucemi webových serverů NCSA, Apache a CERN, aby bylo ukázáno, jak lze skriptové skripty nebo programy C kódovat, aby bylo možné využít nové CGI. Jedním z takových příkladů skriptu byl program CGI s názvem PHF, který implementoval jednoduchý telefonní seznam.

Stejně jako u řady jiných skriptů v té době, tento skript využil funkce: escape_shell_cmd(). Tato funkce měla dezinfikovat její argument, který přišel z uživatelského vstupu a poté předal vstup do unixového shellu, aby byl spuštěn v kontextu zabezpečení webového serveru. Skript nesprávně dezinfikoval veškerý vstup a umožňoval předávání nových řádků do shellu, což ve skutečnosti umožňovalo spouštění více příkazů. Výsledky těchto příkazů se poté zobrazily na webovém serveru. Pokud to kontext zabezpečení webového serveru umožňoval, útočníci mohli spouštět škodlivé příkazy.

Toto byl první rozšířený příklad nového typu webového útoku , kdy nesanitovaná data od webových uživatelů mohla vést ke spuštění kódu na webovém serveru. Protože byl ukázkový kód nainstalován ve výchozím nastavení, útoky byly rozšířené a začátkem roku 1996 vedly k řadě bezpečnostních rad.

Alternativy

Pro každý příchozí požadavek HTTP vytvoří webový server nový proces CGI pro jeho zpracování a po zpracování požadavku HTTP zničí proces CGI. Vytvoření a zničení procesu může spotřebovat mnohem více CPU a paměti než skutečná práce při generování výstupu procesu, zvláště když program CGI stále potřebuje interpretovat virtuální stroj. U vysokého počtu požadavků HTTP může výsledná pracovní zátěž rychle přemoci webový server.

Režie podílejí na tvorbě CGI procesů a destrukce může být snížen z následujících technik:

  • Programy CGI předkompilované do strojového kódu , např. Předkompilované z programů C nebo C ++ , spíše než programy CGI interpretované virtuálním strojem, např . Programy Perl , PHP nebo Python .
  • Rozšíření webového serveru, jako je Apache modulů (např mod_perl , mod_php , Mod_python ), NSAPI pluginy a ISAPI pluginy, které umožňují dlouholetou spuštěné aplikace procesů se stará o více než jednu žádost, a hostil v rámci webového serveru. Web 2.0 umožňuje přenos dat z klienta na server bez použití formulářů HTML a bez povšimnutí uživatele.
  • FastCGI , SCGI a AJP, které umožňují dlouhodobým aplikačním procesům zpracovávat více než jeden požadavek hostovaný externě na webovém serveru. Každý proces aplikace naslouchá na soketu; webový server zpracovává požadavek HTTP a odesílá jej prostřednictvím jiného protokolu (FastCGI, SCGI nebo AJP) do soketu pouze pro dynamický obsah, zatímco statický obsah obvykle zpracovává přímo webový server. Tento přístup vyžaduje méně aplikačních procesů, takže zabírá méně paměti než přístup rozšíření webového serveru. A na rozdíl od převodu aplikačního programu na rozšíření webového serveru zůstávají aplikační programy FastCGI, SCGI a AJP na webovém serveru nezávislé.
  • Jakarta EE spouští aplikace Jakarta Servlet ve webovém kontejneru za účelem poskytování dynamického obsahu a volitelně statického obsahu, který nahrazuje režii při vytváření a ničení procesů mnohem nižší režií při vytváření a ničení vláken . Programátora také vystavuje knihovně dodávané s jazykem Java SE, na které je založena používaná verze Jakarta EE.

Optimální konfigurace pro jakoukoli webovou aplikaci závisí na podrobnostech konkrétních aplikací, množství provozu a složitosti transakce; tyto kompromisy je třeba analyzovat, aby bylo možné určit nejlepší implementaci pro daný úkol a časový rozpočet. Webové rámce nabízejí alternativu k používání skriptů CGI pro interakci s agenty uživatelů.

Viz také

Reference

externí odkazy