Session ID-beskyttelse i PHP. Fallgruver ved å bruke økter i PHP. Sende en verdi eller array ved å bruke en PHP-økt

Hilsen, kjære fellesskap.

Først av alt vil jeg takke deg for en veldig nyttig ressurs. Mer enn en gang har jeg funnet mange interessante ideer og praktiske råd her.

Hensikten med denne artikkelen er å fremheve fallgruvene ved bruk av økter i PHP. Selvfølgelig er det PHP-dokumentasjon og mange eksempler, og denne artikkelen er ikke ment å være en komplett guide. Den er designet for å avsløre noen av nyansene ved å jobbe med økter og beskytte utviklere mot unødvendig sløsing med tid.

Det vanligste eksemplet på bruk av økter er selvfølgelig brukerautorisasjon. La oss starte med den mest grunnleggende implementeringen for å gradvis utvikle den etter hvert som nye oppgaver dukker opp.

(For å spare plass og tid vil vi begrense våre eksempler til kun sesjonsfunksjonene i seg selv, i stedet for å bygge her en fullverdig testapplikasjon med et vakkert klassehierarki, omfattende feilhåndtering og annet godt).

Funksjon startSession() ( // Hvis økten allerede er startet, stopp kjøringen og returner TRUE // (parameteren session.auto_start i php.ini-innstillingsfilen må være deaktivert - standardverdien) if (session_id()) returnerer true; else return session_start(); // Merk: Før versjon 5.3.0 returnerte session_start()-funksjonen TRUE selv om det oppsto en feil. // Hvis du bruker en versjon før 5.3.0, utfør en ekstra sjekk for session_id() // etter å ha kalt session_start() ) funksjon destroySession() ( if (session_id()) ( // Hvis det er en aktiv økt, slett sesjonsinformasjonskapslene, setcookie(session_name(), session_id(), time( )-60*60*24); // og ødelegge økten session_unset( ); session_destroy(); ) )

Merk: Det antas at leseren har grunnleggende kunnskap om PHP-sesjoner, så vi vil ikke dekke prinsippet for driften av funksjonene session_start() og session_destroy() her. Oppgavene med utforming av påloggingsskjemaet og brukerautentisering er ikke relatert til emnet for artikkelen, så vi vil også utelate dem. La meg bare minne deg på at for å identifisere brukeren i hver påfølgende forespørsel, i øyeblikket for vellykket pålogging, må vi lagre brukeridentifikatoren i en øktvariabel (for eksempel kalt bruker-id), som vil være tilgjengelig i alle påfølgende forespørsler innen øktens liv. Det er også nødvendig å implementere behandling av resultatet av vår startSession()-funksjon. Hvis funksjonen returnerer FALSE, vis påloggingsskjemaet i nettleseren. Hvis funksjonen returnerte TRUE, og en sesjonsvariabel som inneholder identifikatoren til den autoriserte brukeren (i vårt tilfelle - bruker-ID), eksisterer - vis siden til den autoriserte brukeren (for mer informasjon om feilhåndtering, se tillegget datert 2013-06- 07 i avsnittet om øktvariabler).

Så langt er alt klart. Spørsmål begynner når du trenger å implementere brukerinaktivitetskontroll (timeout for økter), gjøre det mulig for flere brukere å jobbe samtidig i én nettleser, og også beskytte økter mot uautorisert bruk. Dette vil bli diskutert nedenfor.

Kontrollere brukerinaktivitet ved hjelp av innebygde PHP-verktøy Det første spørsmålet som ofte dukker opp blant utviklere av ulike konsoller for brukere er automatisk avslutning av økten ved inaktivitet fra brukerens side. Det er ikke noe enklere enn å gjøre dette ved å bruke de innebygde egenskapene til PHP. (Dette alternativet er ikke spesielt pålitelig eller fleksibelt, men vi vil vurdere det for fullstendighet).

Funksjon startSession() ( // Tidsavbrudd for brukerinaktivitet (i sekunder) $sessionLifetime = 300; if (session_id()) returnerer true; // Sett cookie-levetiden ini_set("session.cookie_lifetime", $sessionLifetime); // Hvis bruker tidsavbrudd for inaktivitet er satt, angi levetiden for økten på serveren // Merk: For en produksjonsserver anbefales det å forhåndsinnstille disse parameterne i php.ini-filen hvis ($sessionLifetime) ini_set("session.gc_maxlifetime", $sessionLifetime) ; if (session_start( )) ( setcookie(session_name(), session_id(), time()+$sessionLifetime); return true; ) else return false; )

Noen få avklaringer. Som du vet, bestemmer PHP hvilken økt som må startes av informasjonskapselnavnet sendt av nettleseren i forespørselsoverskriften. Nettleseren mottar på sin side denne informasjonskapselen fra serveren, hvor session_start()-funksjonen plasserer den. Hvis nettleserinformasjonskapselen har utløpt, vil den ikke bli sendt i forespørselen, noe som betyr at PHP ikke vil kunne bestemme hvilken økt som skal startes og vil behandle dette som å opprette en ny økt. PHP-innstillingsparameteren session.gc_maxlifetime, som er satt lik vår tidsavbrudd for brukerinaktivitet, setter levetiden til en PHP-økt og kontrolleres av serveren. Å kontrollere øktens levetid fungerer som følger (her ser vi på et eksempel på lagring av økter i midlertidige filer som det vanligste og standardalternativet i PHP).

Når en ny sesjon opprettes, opprettes en fil med navnet sess_ i katalogen som er satt som katalogen for lagring av økter i PHP-innstillingsparameteren session.save_path, hvor er sesjonsidentifikatoren. Deretter, i hver forespørsel, på tidspunktet for lansering av en allerede eksisterende økt, oppdaterer PHP endringstiden for denne filen. Således, i hver påfølgende forespørsel, kan PHP, ved forskjellen mellom gjeldende tidspunkt og tidspunktet for siste endring av øktfilen, bestemme om økten er aktiv eller levetiden allerede er utløpt. (Mekanismen for å slette gamle øktfiler diskuteres mer detaljert i neste avsnitt.)

Merk: Det bør bemerkes her at session.gc_maxlifetime-parameteren gjelder for alle økter innenfor én server (mer presist, innenfor én hoved-PHP-prosess). I praksis betyr dette at hvis flere nettsteder kjører på serveren, og hver av dem har sin egen tidsavbrudd for brukerinaktivitet, så vil innstilling av denne parameteren på en av nettstedene føre til innstillingen for andre nettsteder. Det samme gjelder delt hosting. For å unngå denne situasjonen, brukes separate sesjonskataloger for hvert nettsted på samme server. Innstilling av banen til sessions-katalogen gjøres ved å bruke session.save_path-parameteren i php.ini-innstillingsfilen, eller ved å kalle ini_set()-funksjonen. Etter dette vil øktene til hvert nettsted bli lagret i separate kataloger, og session.gc_maxlifetime-parameteren som er satt på ett av nettstedene, vil kun være gyldig for økten. Vi vil ikke vurdere denne saken i detalj, spesielt siden vi har et mer fleksibelt alternativ for å overvåke brukerinaktivitet.

Kontrollere brukerinaktivitet ved hjelp av øktvariabler Det ser ut til at det forrige alternativet, i all sin enkelhet (bare et par ekstra linjer med kode), gir alt vi trenger. Men hva om ikke hver forespørsel kan betraktes som et resultat av brukeraktivitet? For eksempel har en side en tidtaker som med jevne mellomrom sender en AJAX-forespørsel om å motta oppdateringer fra serveren. En slik forespørsel kan ikke anses som brukeraktivitet, noe som betyr at automatisk forlengelse av øktens levetid ikke er riktig i dette tilfellet. Men vi vet at PHP oppdaterer endringstiden for øktfilen automatisk hver gang session_start()-funksjonen kalles opp, noe som betyr at enhver forespørsel vil føre til en forlengelse av øktens levetid, og tidsavbruddet for brukerinaktivitet vil aldri inntreffe. I tillegg kan den siste merknaden fra forrige seksjon om vanskelighetene med parameteren session.gc_maxlifetime virke for forvirrende og vanskelig å implementere for noen.

For å løse dette problemet vil vi forlate bruken av innebygde PHP-mekanismer og introdusere flere nye øktvariabler som vil tillate oss å kontrollere tidspunktet for brukerinaktivitet selv.

Funksjon startSession($isUserActivity=true) ($sessionLifetime = 300; if (session_id()) returnerer true; // Angi levetiden for informasjonskapsler før du lukker nettleseren (vi vil kontrollere alt på serversiden) ini_set("session. cookie_lifetime", 0); if (! session_start()) returner false; $t = time(); if ($sessionLifetime) ( // Hvis tidsavbruddet for brukerinaktivitet er satt, // sjekk tiden som har gått siden siste brukeraktivitet // (siste forespørselstid da lastactivity session-variabelen ble oppdatert) if (isset($_SESSION["lastactivity"]) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( // Hvis tiden har gått siden brukerens siste aktivitet, / / ​​er større enn tidsavbruddet for inaktivitet, noe som betyr at økten har utløpt og du må avslutte økten destroySession(); return false; ) else ( // Hvis tidsavbruddet ikke har skjedd ennå, // og hvis forespørselen kom som et resultat av brukeraktivitet, // oppdater lastactivity-variabelen med verdien av den gjeldende ene gangen, // forlenger dermed økttiden med en annen sessionLifetime sekunder hvis ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) return true; )

La oss oppsummere. I hver forespørsel sjekker vi om tidsavbruddet er nådd siden siste brukeraktivitet til det aktuelle øyeblikket, og hvis det er nådd, ødelegger vi økten og avbryter utførelsen av funksjonen, og returnerer FALSE. Hvis tidsavbruddet ikke er nådd, og $isUserActivity-parameteren med verdien TRUE sendes til funksjonen, oppdaterer vi tidspunktet for brukerens siste aktivitet. Alt vi trenger å gjøre er å bestemme i kalleskriptet om forespørselen er et resultat av brukeraktivitet, og hvis ikke, kall opp startSession-funksjonen med $isUserActivity-parameteren satt til FALSE.

Tillegg fra 2013-06-07 Behandler resultatet av sessionStart()-funksjonen

Kommentarene påpekte at returnering av FALSE ikke gir en fullstendig forståelse av årsaken til feilen, og dette er helt rettferdig. Jeg publiserte ikke detaljert feilhåndtering her (lengden på artikkelen er allerede ganske stor), siden dette ikke er direkte relatert til artikkelens emne. Men gitt kommentarene, skal jeg avklare.

Som du kan se, kan sessionStart-funksjonen returnere FALSE i to tilfeller. Enten kunne ikke økten startes på grunn av noen interne serverfeil (for eksempel feil sesjonsinnstillinger i php.ini), eller så er øktens levetid utløpt. I det første tilfellet må vi omdirigere brukeren til en side med feil om at det er problemer på serveren og et skjema for å kontakte support. I det andre tilfellet må vi overføre brukeren til påloggingsskjemaet og vise en tilsvarende melding i det om at økten er utløpt. For å gjøre dette, må vi skrive inn feilkoder og returnere den tilsvarende koden i stedet for FALSE, og i ringemetoden sjekke den og handle deretter.

Nå, selv om en økt på serveren fortsatt eksisterer, vil den bli ødelagt første gang den åpnes hvis brukerens tidsavbrudd for inaktivitet har utløpt. Og dette vil skje uavhengig av hvilken øktlevetid som er satt i de globale PHP-innstillingene.

Merk: Hva skjer hvis nettleseren ble lukket og informasjonskapselen for øktnavn ble automatisk ødelagt? Forespørselen til serveren neste gang nettleseren åpnes vil ikke inneholde øktinformasjonskapselen, og serveren vil ikke kunne åpne økten og sjekke brukerens tidsavbrudd for inaktivitet. For oss tilsvarer dette å lage en ny økt og påvirker ikke funksjonalitet eller sikkerhet på noen måte. Men et rettferdig spørsmål dukker opp – hvem vil da ødelegge den gamle økten, hvis vi inntil nå har ødelagt den etter at timeouten er utløpt? Eller vil den nå henge i øktkatalogen for alltid? For å rydde opp i gamle økter i PHP, er det en mekanisme som kalles søppelinnsamling. Den kjører på tidspunktet for neste forespørsel til serveren og sletter alle gamle økter basert på siste endringsdato for øktfilene. Men søppelinnsamlingsmekanismen starter ikke med hver forespørsel til serveren. Frekvensen (eller rettere sagt, sannsynligheten) for lansering bestemmes av to innstillingsparametere session.gc_probability og session.gc_divisor. Resultatet av å dele den første parameteren med den andre er sannsynligheten for å starte søppeloppsamlingsmekanismen. For at sesjonsryddemekanismen skal kunne startes med hver forespørsel til serveren, må disse parameterne settes til like verdier, for eksempel "1". Denne tilnærmingen garanterer en ren sesjonskatalog, men er åpenbart for dyr for serveren. Derfor, på produksjonssystemer, er standardverdien for session.gc_divisor satt til 1000, noe som betyr at søppelinnsamlingsmekanismen vil kjøre med en sannsynlighet på 1/1000. Hvis du eksperimenterer med disse innstillingene i php.ini-filen din, vil du kanskje legge merke til at i tilfellet beskrevet ovenfor, når nettleseren lukker og sletter alle informasjonskapslene, er det fortsatt gamle økter igjen i øktkatalogen en stund. Men dette burde ikke bekymre deg, fordi... som allerede nevnt, påvirker dette ikke på noen måte sikkerheten til mekanismen vår.

Oppdatering fra 2013-06-07 Forhindrer at skript fryser på grunn av låsing av øktfiler

Kommentarene reiste spørsmålet om samtidig kjøring av skript som fryser på grunn av at øktfilen ble blokkert (det mest slående alternativet er lang meningsmåling).

Til å begynne med merker jeg at dette problemet ikke er direkte avhengig av serverbelastningen eller antall brukere. Selvfølgelig, jo flere forespørsler, jo tregere blir skriptene utført. Men dette er en indirekte avhengighet. Problemet vises bare i løpet av én sesjon, når serveren mottar flere forespørsler på vegne av én bruker (for eksempel en av dem er lang avstemning, og resten er vanlige forespørsler). Hver forespørsel prøver å få tilgang til den samme sesjonsfilen, og hvis den forrige forespørselen ikke låste opp filen, vil den påfølgende henge og vente.

For å holde sesjonsfillåsing på et minimum, anbefales det på det sterkeste å lukke økten ved å ringe funksjonen session_write_close() umiddelbart etter at alle handlinger med øktvariabler er fullført. I praksis betyr dette at du ikke skal lagre alt i sesjonsvariabler og få tilgang til dem gjennom hele utføringen av skriptet. Og hvis du trenger å lagre noen arbeidsdata i sesjonsvariabler, så les dem umiddelbart når økten starter, lagre dem i lokale variabler for senere bruk og lukk økten (som betyr å lukke økten med funksjonen session_write_close, og ikke ødelegge den ved å bruke session_destroy ).

I vårt eksempel betyr dette at umiddelbart etter å ha åpnet en økt, sjekket levetiden og eksistensen av en autorisert bruker, må vi lese og lagre alle ekstra øktvariabler som kreves av applikasjonen (hvis noen), og deretter lukke økten ved å ringe til session_write_close() og fortsett kjøringen av et skript, enten det er en lang avstemning eller en vanlig forespørsel.

Beskytte økter mot uautorisert bruk La oss forestille oss en situasjon. En av brukerne dine får en trojaner som frarøver nettleserinformasjonskapslene (der økten vår er lagret) og sender den til den angitte e-posten. Angriperen skaffer seg informasjonskapselen og bruker den til å forfalske en forespørsel på vegne av vår autoriserte bruker. Serveren godtar og behandler denne forespørselen som om den kom fra en autorisert bruker. Hvis ytterligere verifisering av IP-adressen ikke implementeres, vil et slikt angrep føre til en vellykket hacking av brukerens konto med alle påfølgende konsekvenser.

Hvorfor var dette mulig? Selvfølgelig, fordi navnet og sesjonsidentifikatoren alltid er det samme for hele øktens levetid, og hvis du mottar disse dataene, kan du enkelt sende forespørsler på vegne av en annen bruker (selvfølgelig i løpet av denne øktens levetid). Dette er kanskje ikke den vanligste typen angrep, men teoretisk virker det ganske gjennomførbart, spesielt med tanke på at en slik trojaner ikke engang trenger administratorrettigheter for å rane brukerens nettleserinformasjonskapsler.

Hvordan kan du beskytte deg mot angrep av denne typen? Igjen, åpenbart, ved å begrense levetiden til sesjonsidentifikatoren og periodisk endre identifikatoren i samme økt. Vi kan også endre navnet på økten ved å slette den gamle fullstendig og opprette en ny økt, kopiere alle øktvariablene fra den gamle inn i den. Men dette påvirker ikke essensen av tilnærmingen, så for enkelhets skyld vil vi begrense oss til kun sesjonsidentifikatoren.

Det er klart at jo kortere levetid for økt-ID, jo mindre tid vil en angriper ha til å skaffe og bruke informasjonskapsler for å forfalske en brukerforespørsel. Ideelt sett bør en ny identifikator brukes for hver forespørsel, noe som vil minimere muligheten for å bruke andres økt. Men vi vil vurdere det generelle tilfellet når gjenopprettingstiden for øktidentifikatoren er satt vilkårlig.

(Vi vil utelate den delen av koden som allerede er diskutert).

Funksjon startSession($isUserActivity=true) (// Øktidentifikator levetid $idLifetime = 60; ... if ($idLifetime) ( // Hvis levetiden for øktidentifikatoren er satt, // sjekk tiden som har gått siden økten ble opprettet eller siste regenerering // (tidspunkt for siste forespørsel da øktvariabelen starttid ble oppdatert) if (isset($_SESSION["starttid"])) (if ($t-$_SESSION["starttid"] >= $ idLifetime) ( // Tidspunkt hvor levetiden til øktidentifikatoren har utløpt // Generer en ny identifikator session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) else ( // Vi kommer hit hvis økten nettopp har blitt opprettet // Sett tiden for generering av øktidentifikatoren til gjeldende tidspunkt $_SESSION["starttid"] = $t; ) ) return true; )

Så når vi oppretter en ny økt (som oppstår når brukeren logger på), setter vi sesjonsvariabelen starttid, som lagrer for oss tidspunktet for siste generasjon av sesjonsidentifikatoren, til en verdi lik gjeldende servertid. Deretter sjekker vi i hver forespørsel om det har gått nok tid (idLifetime) siden siste generasjon av identifikatoren, og i så fall genererer vi en ny. Derfor, hvis angriperen som mottok informasjonskapselen til den autoriserte brukeren i løpet av den angitte levetiden til identifikatoren ikke har tid til å bruke den, vil den falske forespørselen bli sett på av serveren som uautorisert, og angriperen vil bli ført til påloggingssiden .

Merk: Den nye økt-ID-en kommer inn i nettleserens informasjonskapsel når session_regenerate_id()-funksjonen kalles, som sender den nye informasjonskapselen, lik funksjonen session_start(), så vi trenger ikke å oppdatere informasjonskapselen selv.

Hvis vi ønsker å gjøre øktene våre så sikre som mulig, er det nok å sette levetiden til identifikatoren til én eller til og med fjerne session_regenerate_id()-funksjonen fra parentes og fjerne alle kontroller, noe som vil føre til regenerering av identifikatoren i hver be om. (Jeg har ikke testet effekten av denne tilnærmingen på ytelsen, og jeg kan bare si at funksjonen session_regenerate_id(true) i hovedsak bare utfører 4 handlinger: generere en ny identifikator, lage en header med øktinformasjonskapselen, slette den gamle og lage en ny øktfil).

Lyrisk digresjon: Hvis trojaneren viser seg å være så smart at den ikke sender informasjonskapsler til angriperen, men organiserer sendingen av en forhåndsforberedt falsk forespørsel umiddelbart etter mottak av informasjonskapselen, vil metoden beskrevet ovenfor mest sannsynlig ikke være i stand til å beskytt mot et slikt angrep, fordi mellom det tidspunkt trojaneren mottar informasjonskapselen og sender en falsk forespørsel, vil det praktisk talt ikke være noen forskjell, og det er stor sannsynlighet for at sesjonsidentifikatoren for øyeblikket ikke vil bli regenerert.

Mulighet for samtidig arbeid i én nettleser på vegne av flere brukere. Den siste oppgaven jeg vil vurdere er muligheten for samtidig arbeid i én nettleser av flere brukere. Denne funksjonen er spesielt nyttig på teststadiet, når du trenger å etterligne brukernes samtidige arbeid, og det er tilrådelig å gjøre dette i favorittnettleseren din, i stedet for å bruke hele det tilgjengelige arsenalet eller åpne flere forekomster av nettleseren i inkognitomodus .

I våre tidligere eksempler spesifiserte vi ikke eksplisitt et øktnavn, så standard PHP-navn (PHPSESSID) ble brukt. Dette betyr at alle øktene vi har opprettet så langt har sendt en informasjonskapsel til nettleseren under navnet PHPSESSID. Selvfølgelig, hvis informasjonskapselnavnet alltid er det samme, er det ingen måte å organisere to økter med samme navn i samme nettleser. Men hvis vi brukte vårt eget øktnavn for hver bruker, ville problemet være løst. La oss gjøre det.

Funksjonen startSession($isUserActivity=true, $prefix=null) ( ... if (session_id()) returnerer true; // Hvis brukerprefikset sendes inn i parameterne, // angi et unikt sesjonsnavn som inkluderer dette prefiks, // ellers angi felles navn for alle brukere (for eksempel MYPROJECT) session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); hvis (! session_start()) returnerer usann; ... )

Nå gjenstår det bare å sørge for at det kallende skriptet sender et unikt prefiks for hver bruker til startSession()-funksjonen. Dette kan for eksempel gjøres ved å sende et prefiks i GET/POST-parametrene for hver forespørsel eller gjennom en ekstra informasjonskapsel.

Konklusjon Avslutningsvis vil jeg gi den komplette endelige koden for funksjonene våre for arbeid med PHP-sesjoner, inkludert alle oppgavene diskutert ovenfor.

Funksjonen startSession($isUserActivity=true, $prefix=null) ( $sessionLifetime = 300; $idLifetime = 60; if (session_id()) returnerer true; session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); if (! session_start()) returnerer falsk; $t = tid(); if ($sessionLifetime) (if (isset($_SESSION["lastactivity"] ) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( destroySession(); return false; ) else ( if ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) if ($idLifetime ) ( if (isset($_SESSION["starttid"])) ( if ($t-$_SESSION["starttid"] >= $idLifetime) ( session_regenerate_id(true); $_SESSION["starttid"] = $t; ) ) else ( $_SESSION["starttid"] = $t; ) ) return true; ) funksjon destroySession() ( if (session_id()) ( session_unset(); setcookie(session_name(), session_id(), time() -60*60*24); session_destroy(); ) )

Jeg håper denne artikkelen vil spare litt tid for de som aldri har fordypet seg for dypt i sesjonsmekanismen, og gi nok innsikt i denne mekanismen for de som akkurat har begynt å bli kjent med PHP.

Trenger du brukernavn og passord?

For å sende inn artikler på nett og sjekke statusen til innsendte artikler, må du registrere deg og logge på kontoen din.

Sjekkliste for å forberede en artikkel for innsending

Som en del av artikkelinnsendingsprosessen må forfattere kontrollere at artikkelen deres oppfyller alle de følgende punktene; artikler kan returneres til forfatterne hvis de ikke oppfyller disse kravene.

Artikkelen er utarbeidet i henhold til kravene

Vilkår for overføring av opphavsrett

Forfattere beholder opphavsretten til verket og gir tidsskriftet første publiseringsrettigheter sammen med verket, mens de lisensierer det under vilkårene i Creative Commons Attribution License, som tillater andre å distribuere dette verket med obligatorisk attribusjon til forfatteren av verket og en lenke til den opprinnelige publikasjonen i dette tidsskriftet.

Personvernerklæring

Navn og e-postadresser som er lagt inn på dette magasinets nettsted vil utelukkende brukes til formålene som er angitt av dette bladet og vil ikke bli brukt til andre formål eller gitt til noen annen person eller enhet.

Før registrering i systemet samtykker brukeren i retningslinjene for behandling og lagring av personopplysninger.

Forfatterbetalinger

1500 tegn med mellomrom: 300,00 (RUB)

Publisering av 1 side med manuskript (1500 tegn) - 300 rubler. Grafiske materialer / tabeller betales separat - 50 rubler / 1 stk. Forfatterens kopi, inkludert frakt i Russland, betales på forfatterens forespørsel - 400 rubler. Frakt til utlandet - 800 rubler. Kostnaden for å sende et sertifikat for aksept av materialet for publisering er 150 rubler.

Oversettelse av medfølgende informasjon (fullt navn, forfatterens arbeidssted; tittel; abstrakt; nøkkelord) til engelsk 0,5 rubler for hvert tegn, inkludert mellomrom.

Merk følgende! Forfattere (kandidater og doktorer) som ifølge elibrary.ru har 300 eller flere siteringer (andelen av selvsiteringer bør ikke være mer enn 30%), publiseres gratis. Hvis du er kvalifisert for gratis publisering, når du sender inn materiale, angi i kommentarfeltet en lenke til bibliotekprofilen din med antall siteringer. Fraktkostnader for henting betales separat.

Nettstedets sikkerhet er basert på øktadministrasjon. Når en bruker kobler til et sikkert nettsted, oppgir de legitimasjon, vanligvis i form av et brukernavn og passord. Nettserveren har ingen anelse om hvilken bruker som allerede er pålogget eller hvordan de navigerer fra side til side. Sesjonsmekanismen hindrer brukere i å måtte skrive inn et passord hver gang de vil utføre en ny handling eller gå til en ny side.

I hovedsak sikrer øktadministrasjon at den tilkoblede brukeren er den som ble autentisert. Men dessverre har økter blitt et åpenbart mål for hackere fordi de kan gi tilgang til en webserver uten behov for autentisering.

Etter at brukeren er autentisert, gir webserveren ham en økt-ID. Denne ID-en lagres i nettleseren og erstattes når autentisering er nødvendig. Dette lar deg unngå gjentatte prosesser for innlogging/passord. Alt dette skjer i bakgrunnen og forårsaker ikke ubehag for brukeren. Tenk om du skrev inn brukernavn og passord hver gang du ser på en ny side!

I denne artikkelen vil jeg prøve å skissere alle måtene jeg vet for å beskytte økt-IDen i PHP.

Bruke informasjonskapsler Som standard sendes all øktinformasjon, inkludert ID, til en informasjonskapsel. Men dette skjer ikke alltid. Noen brukere deaktiverer informasjonskapsler i nettleserne. I dette tilfellet vil nettleseren sende økt-ID-en i URL-en.

Her overføres ID-en i klartekst, i motsetning til en økt via en informasjonskapsel, når informasjonen er skjult i HTTP-headeren. Den enkleste måten å beskytte seg mot dette på ville være å forby overføring av sesjonsidentifikatoren gjennom adressefeltet. Dette kan gjøres ved å skrive følgende i Apache-serverens .htaccess-konfigurasjonsfil:

Php_flag session.use_only_cookies på

Bruke kryptering Hvis nettstedet ditt må behandle sensitiv informasjon, for eksempel kredittkortnumre (hei fra Sony), bør du bruke SSL3.0- eller TSL1.0-kryptering. For å gjøre dette, når du angir en informasjonskapsel, må du spesifisere true for den sikre parameteren.

Hvis du lagrer øktpassordet i $_SESSION-variabelen (det er fortsatt bedre å bruke sql), bør du ikke lagre det i klartekst.

If ($_SESSION["passord"] == $userpass) ( // kode)

Koden ovenfor er ikke sikker fordi passordet er lagret som ren tekst i en øktvariabel. Bruk i stedet md5-kryptering, noe som dette:

If ($_SESSION["md5password"] == md5($userpass)) ( // kode)

Nettleserkontroll For å forhindre muligheten for å bruke en økt fra en annen nettleser (datamaskin), bør du angi en kontroll av HTTP-headerfeltet for brukeragenten:

Session_start(); if (isset($_SESSION["HTTP_USER_AGENT"])) ( if ($_SESSION["HTTP_USER_AGENT"] != md5($_SERVER["HTTP_USER_AGENT"])) ( // kode ) ) else ( $_SESSION["HTTP_USER_AGENT" ] = md5($_SERVER["HTTP_USER_AGENT"]); )

Sesjonsutløp Begrens øktens levetid, samt utløpstiden for informasjonskapsler. Som standard er øktvarigheten 1440 sekunder. Du kan endre denne verdien gjennom php.ini og .htaccess. Eksempel for .htaccess:

# Øktens levetid i sekunder
php_value session.gc_maxlifetime 3600
# Cookie-levetid i sekunder
php_value session.cookie_lifetime 3600

Binding med IP-adresse I visse situasjoner (ikke alltid) bør du binde med IP-adresse. Hovedsakelig når antall brukere er begrenset og har statiske IP-er. Kontrollen kan enten være basert på listen over tillatte IP-adresser,

Include("ip_list.php"); //$ip_white_list = array ("admin1" => "111.222.333.444", "admin2" => "555.666.777.888"); if(!empty(array_search($_SERVER["REMOTE_ADDR"],$ip_white_list))) ( header("Location: admin.php"); ) else ( ekko "ACCESS DENY!"; )

Eller etter IP-adresse for hver forespørsel (bare for statisk IP):

If(isset($_SESSION["ip"]) og $_SESSION["ip"] == $_SERVER["REMOTE_ADDR"]) ( header("Location: admin.php"); ) else ( session_unset(); $ _SESSION["ip"] = $_SERVER["REMOTE_ADDR"]; )

Du bør være klar over at hacking ikke kan unngås helt. Du kan bare gjøre dette hacket så vanskelig som mulig på noen kjente måter. Du bør imidlertid heller ikke glemme de lovlige brukerne dine, for ikke å komplisere livene deres med slik beskyttelse.

Denne artikkelen ble skrevet i 2009 og er fortsatt et av våre mest populære innlegg. Hvis du er interessert i å lære mer om PHP og MySQL, kan du finne dette av stor interesse.

MERK: Denne artikkelen har nylig blitt oppdatert for å fungere på PHP 4.2 eller nyere!

Nylig hadde jeg anledning til å jobbe med et lite prosjekt med en gruppe mennesker. Vi hadde tidlig bestemt at e-post alene ikke kom til å være nok til å holde alle oppdatert, så jeg fikk i oppgave å bygge et lite nettsted for prosjektet. Den ville inneholde en enkel meldingstavle, et sted hvor vi kunne laste opp dokumenter og andre filer som resten av teamet kan bruke, og kontaktinformasjon for de forskjellige teammedlemmene.

For at mange av disse funksjonene skulle fungere, visste jeg at jeg ville trenge at brukere logger på før de får tilgang til de relevante delene av nettstedet. Det jeg trengte var et system som ville la brukere registrere seg for en bruker-ID for å få tilgang til nettstedet, og deretter umiddelbart bruke den ID-en uten innblanding fra min side.

I denne artikkelen skal jeg gi en oversikt over systemet jeg utviklet, fra første halvdel med brukerregistreringsprosessen. I andre halvdel vil jeg fokusere på selve nettstedet, hvordan det krever at brukere logger på og deretter opprettholder den påloggede statusen gjennom hele besøket. Jeg vil være spesielt oppmerksom på bruken av øktadministrasjonsfunksjonene i PHP. På slutten bør du ha all informasjonen du trenger for å implementere et lignende system for deg selv.

Gjennom denne artikkelen vil jeg anta at du har en grunnleggende kjennskap til PHP-språket, bruken av skjemaer for å sende informasjon til et PHP-skript, og hvordan PHP kan brukes til å samhandle med en MySQL-database. Hvis noen av disse er fremmede begreper for deg, bør du begynne med å lese min forrige artikkel, .

Del én: Registreringsprosessen Registreringsskjemaet

Et naturlig sted å begynne å bygge et nettsted som krever at brukere registrerer seg for tilgang, er selve registreringsprosessen. Som man kunne forvente, vil et enkelt nettbasert skjema gjøre susen. Slik vil det se ut:

Og her er koden for dette skjemaet:




Ny brukerregistrering



Nytt brukerregistreringsskjema

* indikerer et obligatorisk felt


Med målet klart, vil jeg lede deg gjennom koden for accesscontrol.php. Begynn med å inkludere de to praktiske inkluderingsfilene dine: