Casa / Facebook / Inseriamo una password nella pagina. Protezione tramite password Codice login e password della pagina HTML

Inseriamo una password nella pagina. Protezione tramite password Codice login e password della pagina HTML

Quindi, il nostro compito è impostare una password per accedere a una determinata pagina. Cominciamo con il metodo più primitivo, per così dire, di protezione: poche righe in JavaScript:

Var pass = prompt("Inserisci la password:", ""); if (pass == null) window.location = "wrong.html"; else if (pass.toLowerCase() == "wwvsfc") window.location = "temp.html"; else window.location = "wrong.html"; Trucchi come nascondere uno script in un file separato utilizzando un costrutto non cambiano sostanzialmente nulla.

Un sistema simile implementato in Java:

Importa java.applet.*; importa java.awt.*; importa java.net.*; public class Password extends Applet( TextField login, password; String Login = "login"; String Password = "Password"; public Password() ( ) public void init() ( Panel panel = new Panel(); panel.setLayout(new GridLayout(2,2)); login = nuovo TextField(20); password = nuovo TextField(20); panel.add(new Label("Login:")); panel.add(login); panel.add(new Label("Password:")); pannello.add(password); add(pannello); add(nuovo pulsante("Ok")); ) azione booleana pubblica(Evento evt, Oggetto obj) ( if(evt.target istanza di Pulsante) ( String s; if(login.getText().equals(Login) && password.getText().equals(Password)) ( s = "http://www.hackzone.ru/articles/ok.html" ; ) else ( s = "http://www.hackzone.ru/articles/bad.html"; ) try ( getAppletContext().showDocument(nuovi URL(s)); ) catch(Exception e) ( password.setText (e.toString()); ) restituisce vero; ) restituisce falso; ))

Includendo questa applet in una pagina, puoi ottenere qualcosa di simile a questo (tutti gli esempi successivi utilizzano ok.html e bad.html):

Controllo password

Può essere reso più intelligente, creare una pagina separata per ciascun utente, forzarlo a leggere i dati da un file, ecc. Lo svantaggio fondamentale è che una volta che una persona è arrivata sulla pagina che sta cercando, nessuno può impedirgli di ricordare questo URL, quindi si tratta di uno strumento utilizzabile una sola volta. Certo, puoi nascondere la pagina all'interno di un frame in modo che l'URL non appaia nella barra degli indirizzi, ma capisci da chi proviene questa protezione. Anche in questo caso l'applet va interamente al client ed è, in linea di principio, completamente disponibile per la ricerca.

La soluzione basata sull'utilizzo della CGI non presenta quest'ultimo inconveniente. Un semplice script Perl assomiglia a questo:

#!/usr/bin/perluse CGI qw(:standard); $query = nuovo CGI;$ok = "ok.html";$indirizzo = "bad.html"; $login = "accedi";$password = "password"; $l = $query->param("login"); $p = $query->param("password"); if(($p eq $password) && ($l eq $login))( $indirizzo = $ok;)print $query->reindirizza($indirizzo);

Esempio di utilizzo:

Controllo password

Per ovviare al primo inconveniente, puoi generare dinamicamente una nuova pagina basata su quella nascosta da qualche parte all'interno, senza fornire l'URL.

Codice modificato:

#!/usr/bin/perluse CGI qw(:standard); $query = nuovo CGI; $ok = "ok.html"; $indirizzo = "bad.html"; $docroot = $ENV("DOCUMENT_ROOT"); $localpath = "/articoli/"; $login = "accedi";$password = "password"; $l = $query->param("login"); $p = $query->param("password"); if(($p eq $password) && ($l eq $login))( $indirizzo = $ok;) print $query->intestazione(); open(FL, $docroot.$localpath.$indirizzo); while())(# Qui, allo stesso tempo, puoi modificare al volo il codice html# Perché? Beh, non si sa mai... :) print $_;) close (FL);

Esempio di utilizzo:

Controllo password

Come potete vedere, l'URL del file non viene più visualizzato, anche se a scapito dell'SSI (può però essere semplicemente catturato durante l'output ed elaborato manualmente), ma anche qui rimane la possibilità teorica di indovinare l'URL e non dobbiamo dimenticare che tutti i tipi di immagini incluse possono rendere un disservizio alle pagine, ovviamente quando si utilizzano percorsi relativi.

Infine, il modo più affidabile per impostare una password di accesso è utilizzare gli strumenti del server: non per niente le persone li hanno utilizzati, dopo tutto. Mi concentrerò su due: Apache come il più popolare e IIS come altrettanto popolare :)

Con IIS tutto è abbastanza semplice: la protezione viene eseguita utilizzando NTFS, il che, ovviamente, limita in qualche modo le capacità degli amministratori non server. L'idea è la seguente: all'utente IUSR_xxxx, sotto il cui account lavorano per impostazione predefinita tutti i visitatori del sito, viene negato l'accesso al file/directory desiderato. Successivamente, solo gli utenti per i quali ciò è esplicitamente specificato in Proprietà->Sicurezza avranno accesso a questi file. È chiaro che è molto più conveniente unirli in gruppi. Ci sono un paio di sottigliezze qui. In primo luogo, agli utenti specificati deve essere assegnato il diritto di accesso locale (Criteri->Diritti utente in Gestione utenti). In secondo luogo, se non si seleziona il servizio WWW Autenticazione di base (testo non crittografato) nelle impostazioni WWW, solo gli utenti di Internet Explorer verranno consentito entrare.

In Apache, tutto è fatto in modo leggermente diverso. La protezione è impostata a livello di directory. Le direttive corrispondenti possono essere inserite sia nel file di configurazione generale php.ini che nei file .htaccess. L’insieme delle direttive in entrambi i casi è lo stesso e per la maggior parte delle persone che affittano spazio per un sito web/una pagina sul server di qualcun altro, la prima opzione non è disponibile. Quindi, crei un file .htaccess nella directory a cui intendi limitare l'accesso, quindi inserisci al suo interno le seguenti direttive:

AuthType tipo di controllo- Di solito viene utilizzato Basic.

NomeAut Nome- specifica il nome dell'area in cui sono validi nomi utente e password. Questo è lo stesso nome che il browser mostra nella finestra di dialogo della password. Impostando uno di questi nomi per directory diverse, puoi risparmiare agli utenti il ​​tempo di inserire una password aggiuntiva.

File gruppoaut Nome- specifica il nome del file in cui sono memorizzati i nomi dei gruppi e dei loro membri. Il suo formato:
gruppo1: membro1 membro2 ...
gruppo2: membro3 membro4 ...

AuthUserFile Nome- specifica il nome del file con le password. In generale, per generarlo è necessario utilizzare l'utilità htpasswd dalla distribuzione Apache. Ma almeno per alcune versioni del server, questo formato è così:
utente1: passwordhash1
utente2: passwordhash2

Passwordhash può essere facilmente ottenuto utilizzando la funzione Perl standard:
$hash=cripta($passaggio,$sale);
dove $pass è la password, $salt è una stringa di due caratteri coinvolta nella generazione dell'hash.

Quindi è del tutto possibile automatizzare il processo di aggiunta di nuovi utenti, modifica delle password tramite moduli html, ecc.

richiedono utente utente1 utente2 e richiedono un gruppo utente1 utente2 consentono di specificare quali utenti e gruppi avranno accesso a una determinata directory.

richiede utente-valido consente l'accesso a tutti gli utenti specificati nel file delle password di sistema.

... , dove metodo io definisce un metodo HTTP. Ad esempio, limita l'uso di non-direttive nidificate ai casi di utilizzo dei metodi GET e POST (di solito questo è più che sufficiente).Le direttive nidificate possono essere require, order, consenti e nega.

Un'altra coppia di direttive utili sono "deny" e "allow", rispettivamente negazione e autorizzazione dell'accesso, e vengono utilizzate in questo modo:
negato da tutti
consentire da 192.168

Per impostazione predefinita, tutti i rifiuti vengono eseguiti per primi, quindi tutti i rifiuti, quindi consenti da tutti consentirà l'accesso a tutti gli utenti, indipendentemente da eventuali rifiuti. L'ordine può essere modificato con la direttiva dell'ordine: order let, descend .

Deny from all va bene con il secondo metodo di protezione delle pagine tramite CGI; è questa direttiva la migliore per coprire tutti i tipi di password per i libri degli ospiti, ecc. Quando tenta di accedere alle pagine da questa directory, l'utente riceverà un messaggio relativo a una pagina inesistente.

A proposito, qui, di sfuggita, viene dimostrata la gestione indipendente degli errori: in questo caso, il codice 403, Forbidden. I preferiti di tutti 404 - Non trovato e 401 - Non autorizzato vengono elaborati allo stesso modo. Per fare ciò basta aggiungere la direttiva ErrorDocument a .htaccess codice url:
ErrorDocument 404 /cgi-bin/bad.pl
ErrorDocument 403 /cgi-bin/badaccess.pl
ErrorDocument 401 /cgi-bin/badaccess.pl

Tutto ciò che lo script fa è generare un messaggio di errore utilizzando la variabile d'ambiente REQUEST_URI, quindi puoi semplicemente puntare a una pagina adatta.

Per l'esempio finale, utilizziamo un file .htaccess con il seguente contenuto:

AuthType BasicAuthName TestAuthGroupFile /my/local/path/tgroupAuthUserFile /my/local/path/tuserrequire test del gruppo

C'è solo una riga nel file tgroup - prova: prova di accesso, nel file tuser - password crittografate per login (password) e test (test). Tieni presente che quando accedi nuovamente a questa pagina, il browser capisce di essere appena entrato in quest'area e non disturba l'utente con una richiesta di password non necessaria.

Questo è, in sintesi, l'insieme minimo di informazioni necessarie per proteggere le pagine web. Come dimostra la pratica, dovresti fidarti più o meno solo delle soluzioni basate sugli strumenti forniti dal server (e poi finché non viene scoperto un altro buco nel server), quindi se possibile è meglio sceglierli.


Cari amici, sono felice di accogliervi nuovamente sul mio blog” . Oggi parleremo di come impostare una password su una pagina del sito WordPress, qui è tutto molto semplice, ma a cosa serve? Cercherò di rispondere a queste e ad altre domande per te oggi.

Perché inserire una password nella pagina?

A volte è necessario limitare l'accesso ad alcune sezioni del sito; queste sezioni possono contenere informazioni per utenti privilegiati (cosa spesso praticata), oppure l'accesso a sezioni nascoste può essere a pagamento. Il canone può essere addebitato una volta oppure sotto forma di canone di abbonamento, ad esempio una volta al mese. In questo modo puoi creare una pagina web sicura e fornire accesso a pagamento ai tuoi visitatori.

Al giorno d'oggi ci sono molte offerte su Internet in cui si propone di prendere parte a corsi di formazione a pagamento o acquistare un corso sul tema della monetizzazione di siti con accesso a pagamento a determinate pagine, ma non vale la pena acquistarli. Molto probabilmente non troverai nulla di nuovo lì, ma imparerai come impostare una password su una pagina del sito e come modificarla in questo articolo, in modo completamente gratuito.

Penso che il principio per guadagnare con l'accesso a pagamento sia chiaro: imposta una password, accetta il pagamento, invia la password di accesso. Se si tratta di un canone di abbonamento, cambia la password una volta al mese, riscuoti nuovamente il pagamento e invia una nuova password. Tutto questo può essere automatizzato utilizzando l'eccellente servizio e-autopay.com, questo servizio è molto conveniente in termini di accettazione di pagamenti e invio automatico di beni elettronici e fisici, codici PIN e così via, tutto può essere configurato in un comodo programma di affiliazione, io ti consiglio di prestare attenzione, il servizio è utilizzato da tutti i noti uomini d'affari dell'informazione come Azamat Ushanov, Alexander Borisov e molti altri. A proposito, è implementato anche sul servizio e-autopay.com.

Ora scopriamo come impostare una password su una pagina del sito WordPress. Per fare ciò, ovviamente, dobbiamo prima creare la pagina desiderata, quindi andare a modificare il post e andare alla scheda "Pubblica" e fare clic sul collegamento "modifica", vedere la figura.

Quindi vedrai la seguente finestra in cui puoi selezionare visibilità, pubblica, privata o protetta da password, e puoi anche appuntare la pagina in alto nella Home page, ma abbiamo bisogno di una password, seleziona la funzione desiderata e imposta una password per la pagina, come mostrato nella figura seguente.

Dopo tutti i passaggi precedenti, tutto ciò che devi fare è pubblicare la pagina al momento giusto. In questo modo semplice, puoi creare pagine con password sul tuo blog e creare così un accesso a pagamento o limitato a varie informazioni. Ad esempio sul mio blog l'accesso ad un corso gratuito è limitato, l'accesso si ottiene solo dopo l'iscrizione a questo corso, dopo aver attivato l'abbonamento, viene inviata alla tua email una password di accesso, tutto è molto semplice e tutto è automatico. Come puoi vedere, non c'è nulla di complicato in questo; puoi impostare password su qualsiasi pagina e articolo del tuo sito.

Ora sai come inserire una password in una pagina o in un articolo di un sito. Spero che queste informazioni ti offrano vantaggi e nuove idee per guadagnare soldi con il tuo sito web. Come sempre, attendo con ansia le vostre domande e commenti su questo articolo.

Inserisci una password nella pagina

Questo articolo non pretende di essere una rivelazione; tutte queste cose sono abbastanza ovvie e ampiamente conosciute. Tuttavia, avendo recentemente ricevuto diverse domande sulla limitazione dell'accesso alle pagine Web, ho deciso di riunire le risposte.

Quindi, il nostro compito è impostare una password per accedere a una determinata pagina. Cominciamo con il metodo più primitivo, per così dire, di protezione: poche righe di JavaScript. Il codice è qualcosa come

Var pass = prompt("Inserisci la password:", ""); if (pass == null) window.location = "bad.html"; else if (pass.toLowerCase() == "password") window.location = "ok.html"; else window.location = "bad..js"> non cambia sostanzialmente nulla.

A un livello superiore esiste un sistema simile implementato in Java.

Di seguito è riportato il codice sorgente semplificato.

Importa java.applet.*; importa java.awt.*; importa java.net.*; public class Password extends Applet ( TextField login, password; String Login = "login"; String Password = "Password"; public Password() ( ) public void init() ( Panel panel = new Panel(); panel.setLayout(new GridLayout(2,2)); login = nuovo TextField(20); password = nuovo TextField(20); panel.add(new Label("Login:")); panel.add(login); panel.add(new Label("Password:")); pannello.add(password); add(pannello); add(nuovo pulsante("Ok")); ) azione booleana pubblica(Evento evt, Oggetto obj) ( if(evt.target istanza di Pulsante) ( String s; if(login.getText().equals(Login) && password.getText().equals(Password)) ( s = "http://www.webclub.ru/materials/ pagepsw/ok. html"; ) else ( s = "http://www.webclub.ru/materials/pagepsw/bad.html"; ) try ( getAppletContext().showDocument (nuovi URL); ) catch(Eccezione e) ( password.setText(e.toString()); ) restituisce vero; ) restituisce falso; ) )

Includendo questa applet in una pagina, puoi ottenere qualcosa di simile a questo:

Controllo password

Può essere reso più intelligente, creare una pagina separata per ciascun utente, forzarlo a leggere i dati da un file, ecc. Lo svantaggio fondamentale è che una volta che una persona è arrivata sulla pagina che sta cercando, nessuno può impedirgli di ricordare questo URL, quindi si tratta di uno strumento utilizzabile una sola volta. Certo, puoi nascondere la pagina all'interno di un frame in modo che l'URL non appaia nella barra degli indirizzi, ma capisci da chi proviene questa protezione. Anche in questo caso l'applet va interamente al client ed è, in linea di principio, completamente disponibile per la ricerca.

La soluzione basata sull'utilizzo della CGI non presenta quest'ultimo inconveniente. Un semplice script Perl assomiglia a questo:

#!/usr/bin/perl usa CGI qw(:standard); $query = nuovo CGI; $ok = "ok.html"; $indirizzo = "bad.html"; $login = "accedi"; $password = "password"; $l = $query->param("login"); $p = $query->param("password"); if(($p eq $password) && ($l eq $login)) ( $indirizzo = $ok; ) print $query->reindirizza($indirizzo);

Esempio di utilizzo:

Controllo password

Per ovviare al primo inconveniente, puoi generare dinamicamente una nuova pagina basata su quella nascosta da qualche parte all'interno, senza fornire l'URL.

Codice modificato:

#!/usr/bin/perl usa CGI qw(:standard); $query = nuovo CGI; $ok = "ok.html"; $indirizzo = "bad.html"; $docroot = $ENV("DOCUMENT_ROOT"); $localpath = "/materials/pagepsw/"; $login = "accedi"; $password = "password"; $l = $query->param("login"); $p = $query->param("password"); if(($p eq $password) && ($l eq $login)) ( $indirizzo = $ok; ) print $query->intestazione(); open(FL, $docroot.$localpath.$indirizzo); while() ( # Qui puoi anche modificare il codice html al volo # Perché? Beh, non si sa mai... :) print $_; )chiudi(FL);

Esempio di utilizzo:

Controllo password

Come puoi vedere, l'URL del file non viene più visualizzato, anche se a costo di SSI, se era presente qualcosa di simile (questo può però essere catturato durante l'output ed elaborato manualmente). Ma anche qui resta teoricamente la possibilità di indovinare l'URL, e non dobbiamo dimenticare che tutti i tipi di immagini incluse nelle pagine possono causare un disservizio, ovviamente quando si utilizzano percorsi relativi.

Infine, il modo più affidabile per impostare una password di accesso è utilizzare gli strumenti del server: non per niente le persone li hanno utilizzati, dopo tutto. Mi concentrerò su due: Apache come il più popolare e IIS come altrettanto popolare :)

Con IIS tutto è abbastanza semplice: la protezione viene eseguita utilizzando NTFS, il che, ovviamente, limita in qualche modo le capacità degli amministratori non server. L'idea è la seguente: all'utente IUSR_xxxx, sotto il cui account lavorano per impostazione predefinita tutti i visitatori del sito, viene negato l'accesso al file/directory desiderato. Successivamente, solo gli utenti per i quali ciò è esplicitamente specificato in Proprietà->Sicurezza avranno accesso a questi file. È chiaro che è molto più conveniente unirli in gruppi. Ci sono un paio di sottigliezze qui. In primo luogo, agli utenti specificati deve essere assegnato il diritto di accesso locale (Criteri->Diritti utente in Gestione utenti). In secondo luogo, se non si seleziona il servizio WWW Autenticazione di base (testo non crittografato) nelle impostazioni WWW, solo gli utenti di Internet Explorer verranno consentito in "A.

In Apache, tutto è fatto in modo leggermente diverso. La protezione è impostata a livello di directory. Le direttive corrispondenti possono essere inserite sia nel file di configurazione generale (nella sezione) che nei file .htaccess. L’insieme delle direttive in entrambi i casi è lo stesso e per la maggior parte delle persone che affittano spazio per un sito web/una pagina sul server di qualcun altro, il secondo metodo è molto più rilevante. Quindi, crei un file .htaccess nella directory a cui intendi limitare l'accesso, quindi inserisci al suo interno le seguenti direttive (elencherò le principali):

AuthType tipo di controllo- Di solito viene utilizzato Basic.

NomeAut Nome- specifica il nome dell'area in cui sono validi nomi utente e password. Questo è lo stesso nome che il browser mostra nella finestra di dialogo della password. Impostando uno di questi nomi per directory diverse, puoi risparmiare agli utenti il ​​tempo di inserire una password aggiuntiva.

File gruppoaut Nome- specifica il nome del file in cui sono memorizzati i nomi dei gruppi e dei loro membri. Il suo formato:
gruppo1: membro1 membro2 ...
gruppo2: membro3 membro4 ...

AuthUserFile Nome- specifica il nome del file con le password. In generale, per generarlo è necessario utilizzare l'utilità htpasswd dalla distribuzione Apache. Ma almeno per alcune versioni del server, questo formato è così:
utente1: passwordhash1
utente2: passwordhash2

Passwordhash può essere facilmente ottenuto utilizzando la funzione Perl standard:
$hash=cripta($passaggio,$sale);
dove $pass è la password, $salt è una stringa di due caratteri coinvolta nella generazione dell'hash.

Quindi è del tutto possibile automatizzare il processo di aggiunta di nuovi utenti, modifica delle password tramite moduli html, ecc.

richiedono utente utente1 utente2 e richiedono un gruppo utente1 utente2 consentono di specificare quali utenti e gruppi avranno accesso a una determinata directory.

richiede utente-valido consente l'accesso a tutti gli utenti specificati nel file delle password di sistema.

... , dove metodo io definisce un metodo HTTP. Ad esempio, limita l'uso di direttive nidificate ai casi di utilizzo dei metodi GET e POST (di solito questo è più che sufficiente). Le direttive possono essere nidificate: richiedi, ordina, consenti e nega.

Un'altra coppia di direttive utili sono negare e consentire: rispettivamente negare e consentire l'accesso. Applica qualcosa del genere:
negato da tutti
consentire da 192.168

Per impostazione predefinita, vengono eseguiti prima tutti i rifiuti, quindi tutti i consenti, quindi consenti da tutti consentirà l'accesso a tutti gli utenti, indipendentemente da qualsiasi rifiuto. L'ordine può essere modificato con la direttiva ordine: ordine consenti, nega.

Deny from all va bene con il secondo metodo di protezione delle pagine tramite CGI; è questa direttiva la migliore per coprire tutti i tipi di password per i libri degli ospiti, ecc.

A proposito, qui, di sfuggita, viene dimostrata la gestione indipendente degli errori: in questo caso, il codice 403, Forbidden. Gli amati 404, Not Found e 401, Unauthorized vengono elaborati in modo simile. Per fare ciò basta aggiungere la direttiva ErrorDocument a .htaccess codice url:
ErrorDocument 404 /cgi-bin/bad.pl
ErrorDocument 403 /cgi-bin/badaccess.pl
ErrorDocument 401 /cgi-bin/badaccess.pl

Tutto ciò che lo script fa è generare un messaggio di errore utilizzando la variabile d'ambiente REQUEST_URI, quindi puoi semplicemente puntare a una pagina adatta.

Per l'esempio finale, utilizziamo un file .htaccess con il seguente contenuto:

AuthType Test AuthName di base AuthGroupFile /.../pagepsw/deny/tgroup AuthUserFile /.../pagepsw/deny/tuser richiede il test del gruppo

C'è solo una riga nel file tgroup - prova: prova di accesso, nel file tuser - password crittografate per login (password) e test (test). Tieni presente che quando accedi nuovamente a questa pagina, il browser capisce di essere appena entrato in quest'area e non disturba l'utente con una richiesta di password non necessaria.

Questo è, in sintesi, l'insieme minimo di informazioni necessarie per proteggere le pagine web. Come dimostra la pratica, dovresti fidarti più o meno solo delle soluzioni basate sugli strumenti forniti dal server (e poi finché non viene scoperto un altro buco nel server), quindi se possibile è meglio sceglierli.

Vengono discussi semplici modi per bloccare una directory o file con una password. Come autorizzare un utente tramite i cookie. Identificazione dell'utente attraverso il meccanismo di sessione integrato in PHP4.

Password per la pagina. Parte 1. Piuttosto teorica.

Ho deciso di descrivere i modi per proteggere parte del sito con una password. L'argomento in realtà è piuttosto vasto, quindi per la prima volta mi limiterò all'autorizzazione php+mysql.

La prima domanda che di solito sorge è come chiudere la directory con gli script di amministrazione con una password. In questo caso non sono necessari fronzoli: uno o più amministratori hanno gli stessi diritti e le personalità raramente cambiano. Il modo più semplice in questa situazione è utilizzare l'autorizzazione del server standard: inserire i file .htaccess e .htpasswd e scrivere in essi i parametri necessari.

Aggiungo due cose. Il primo è dove mettere il file .htpasswd. Sperimentalmente ho scoperto che se, ad esempio, il percorso di un documento con un messaggio di errore (ErrorDocument) viene scritto rispetto alla variabile di sistema DocumentRoot. Ma il percorso del file della password (UserFile) è scritto rispetto a ServerRoot. Per quanto ho capito, non puoi inserire .htpasswd sopra ServerRoot - "../" non viene percepito. Tutto ciò viene fatto in modo che sia possibile posizionare un file con password, ad esempio, un livello sopra la directory principale del sito, in modo che non vi sia alcun accesso al file dalla rete.

La seconda è che lo script possa scoprire chi lo sta aprendo e la password: le variabili $PHP_AUTH_USER e $PHP_AUTH_PW.

Lo svantaggio principale di questo metodo è che il server non può bloccare l'ipotesi della password (dopo diversi tentativi di accesso falliti, all'utente viene chiesto di attendere un'ora o due e durante questo periodo le chiamate dal suo indirizzo IP vengono ignorate). Questo è scritto nella documentazione ufficiale di Apache.

Un altro inconveniente è la necessità di riscrivere i file con le password quando si elimina un utente o se ne introduce uno nuovo. Ma se ciò accade raramente, questo metodo è più che sufficiente e non dovrai preoccuparti di scrivere un meccanismo di autorizzazione.

Automazione dell'autorizzazione

Ciò è necessario non solo per semplificare il lavoro con un gran numero di utenti e il loro elevato turnover. Se è necessario conservare informazioni aggiuntive sugli utenti o se è necessaria una differenziazione flessibile dei diritti, è meglio trasferire l'autorizzazione al database.

Ogni pagina di un territorio chiuso include un file con il seguente codice:

$risultato = mysql_query(" SELECT * FROM persona WHERE login="". preg_replace("/[^\\w_-]/","",$PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW) """); if (@mysql_num_rows($risultato)!=1) ( header("WWW-Authenticate: Basic realm=\"Area utente\""); header("HTTP/1.0 401 Non autorizzato"); print("Per accedere al nell'area utente del sito, è necessario inserire nome utente e password."); exit(); ); $riga_utente = mysql_fetch_array($risultato);

Nella prima riga, tutti i caratteri tranne lettere, numeri, trattini e trattini bassi vengono rimossi dal login. Viene quindi controllato il numero di righe ricevute e solo se si tratta di una riga viene concesso l'accesso. In altri casi, l'utente vedrà una finestra nel browser che richiede di inserire login e password. Se l'utente ha effettuato l'accesso con successo, abbiamo tutte le informazioni su di lui nell'array $user_row.

Naturalmente, l’esempio che ho fornito presenta una serie di carenze significative. Non riscriverlo uno a uno, per non cadere vittima di tentativi di indovinare la password, perché
1. qui non esiste alcuna protezione contro la selezione
2. se la tabella utente è grande, quando indovina la password, molto probabilmente un utente malintenzionato travolgerà il database

E l'ultimo metodo per oggi è archiviare dati crittografati nei cookie.

C'è uno script per l'accesso, il resto include un codice che ti consente di continuare le azioni solo in un'area chiusa: se i cookie scadono o esci da lì, dovrai tornare alla pagina di accesso.

Lo script di input controlla il login e la password ed emette due cookie. Nel primo - il login, per identificare immediatamente l'utente (nel database il campo login è, ovviamente, unico o addirittura chiave). Il secondo cookie contiene l'hash dell'ora di accesso e della password (per completezza di segretezza, aggiungo la lettera "Y" a queste righe - quindi è quasi impossibile trovare l'hash :).

Tutti gli altri programmi includono codice che esegue le seguenti operazioni. Effettua una richiesta al database: seleziona la riga con il login ricevuto. Da questa riga prende il campo “log_time” e la password e ne crea un hash, come descritto sopra. Lo confronta con quello che ha ricevuto e, se corrispondono, emette un nuovo cookie hash, ancora una volta, dalla password, dall'ora e dalla lettera "Y" ed effettua una query al database "UPDATE utente SET log_time="..." DOVE login = "$cookie_login"".

If (isset($HTTP_COOKIE_VARS[$cookie_login]) && isset($HTTP_COOKIE_VARS[$cookie_code])) ( $login = $HTTP_COOKIE_VARS[$cookie_login]; $code = $HTTP_COOKIE_VARS[$cookie_code]; $risultato = mysql_query("SELECT date_format(log_date,"%Y%m%d%H%i%s") come log_date1,pass,uid DALL'utente DOVE email="$login" E log_date>"DATA_SUB(ORA(),INTERVALLO 15 MINUTI)"" ); if (!mysql_error() && @mysql_num_rows($risultato)==1) ( $log_time0 = ora(); $log_time1 = date("YmdHis", $log_time0); $log_time2 = date("Y-m-d H:i :s", $log_time0); $current_user = mysql_fetch_array($result); if (md5($current_user["pass"].$current_user["log_date1"].$md5letter) == $code) ( mysql_query("AGGIORNA utente SET log_date="$log_time2" WHERE uid=".$current_user["uid"]); setcookie($cookie_code, md5($current_user["pass"].$log_time1.$md5lettera), ora()+900, $percorso_sito); $auth = true; ) altrimenti unset($current_user); ); );

Ancora una volta, qui non c'è protezione dalla selezione e dall'attacco al server (a proposito, qui puoi scrivere l'indirizzo IP dell'utente invece della lettera "Y" - in modo che, ad esempio, un vicino di ufficio non possa prendere un file con un cookie ed effettuare l'accesso dal suo computer).

Password per la pagina. Parte 2. Blocco delle assunzioni

Quando ho postato questo problema l'ultima volta, mi hanno preso a calci sul posto, dicendo che un blocco del genere avrebbe potuto far deragliare il server.

Ma prima parliamo del blocco del rimbalzo. Banalità, ma comunque. Una password di dieci caratteri composta da lettere latine e numeri significa che ci sono molte opzioni. Se indovini una password 1.000.000 di volte al secondo, ci vorranno diverse migliaia di anni. Ma poiché queste parole incomprensibili sono difficili da ricordare, spesso creiamo password con parole significative. Alcuni anni fa si è scoperto che la maggior parte delle password può essere indovinata utilizzando un dizionario di 10.000 parole. Un tempo, sulla rete apparve un worm (un virus del genere) che si insinuò nei server Unix, sfruttando le loro falle di sicurezza, e raccolse password per utenti privilegiati utilizzando... il dizionario ortografico del sistema Unix. Non c'era bisogno di portare nulla!

Ogni utente, finché non ha inserito login e password corretti, è considerato un hacker malvagio. Di cosa ci occupiamo quando l'utente inserisce qualcosa in modo errato?

  • dimenticanza (per questo i siti decenti dispongono di un modulo “password dimenticata” per inviare la stessa password all'e-mail inserita nelle impostazioni di sistema)
  • coccole (“perché non mi interessa”)
  • selezione della password tramite dizionario (la probabilità di una selezione riuscita è alta, quindi è necessario chiuderla, soprattutto se il sito è di natura commerciale)
  • Attacco DoS (per non sovraccaricare il server è necessario ridurre al minimo le azioni che lo script eseguirà in questo caso)

    Ho pensato a lungo a come potrei causare un sovraccarico sul server se il meccanismo di protezione si basa sui file. Si è rivelato facile (quanto costerà è un'altra domanda). Quindi, diciamo che il server non sarà in grado di gestirlo se lo script tenta di aprire file in scrittura 1000 volte al secondo e di scrivervi dati. Poiché dopo 5 tentativi di accesso falliti, all'utente verrà immediatamente negato l'accesso (senza che alcun dato venga scritto nel file), è necessario trovare 200 IP univoci, dai quali è necessario contattare cinque volte ciascuno. È possibile. Appendiamo un banner html con cinque tag nello scroller del banner:

    L'utente effettua immediatamente cinque richieste, il server scrive sul file cinque volte (a proposito, in alcuni browser potrebbe apparire una finestra per l'inserimento di login e password). Puoi creare una pagina HTML con cinque di queste immagini e inserire la pagina stessa tramite un iframe nel sito che stai visitando (tramite un iframe - in modo che il campo referer non venga trovato. È improbabile che il servizio di supporto di un servizio gratuito l'hosting si occuperà di cose come scavare nei file di registro alla ricerca di referrer). Gli esempi che ho fornito sono, ovviamente, inverosimili, ma è dimostrato il fatto stesso che si possa trarre vantaggio da un simile difetto del sistema. A proposito, qualcosa di simile è già successo.

    Ma darò comunque questo metodo: l'ho scritto invano, o cosa? A proposito, può essere utilizzato senza troppi timori per un numero limitato di indirizzi (ad esempio, per la rete locale di un'azienda) inserendo nella directory un file .htaccess con il seguente contenuto:

    Ordina nega, consenti nega da tutti consenti da xxx.xxx.xxx

    Ed ecco il codice del programma:

    $errori = 0; $fn = "ignora/". preg_replace("[^\d\.]", "", $REMOTE_ADDR. ".". $HTTP_FORWARDED_FOR); if (is_file($fn)) ( if (filectime($fn)< time()-3600) unlink($fn); else $errors = fread(fopen($fn, "r"), 2); }; if ($errors>5) ( print ("L'accesso è chiuso. Torna tra un'ora."); exit(); );

    // qui viene stabilita la connessione con il server del database. per non toccarsi invano se l'utilizzatore viene subito “picchiato”.

    $risultato = mysql_query("SELECT * FROM utente WHERE login="". preg_replace("/[^\w_\-]/", "", $PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW) """); if (@mysql_num_rows($risultato)!=1) ( header("WWW-Authenticate: Basic realm=\"area segreta\""); header("HTTP/1.0 401 Non autorizzato"); print ("Autorizzazione richiesta") ; fwrite(fopen($fn, "w"), ++$errors); exit(); ); $utente_corrente = mysql_fetch_array($risultato); mysql_free_result($risultato);

    Tuttavia, è un peccato lavorare con i file se è presente un database. Scherzo. Per le autorizzazioni non riuscite, crea una tabella:

    CREATE TABLE unauth (nome utente VARCHAR(64) NOT NULL, passa VARCHAR(64) NOT NULL, ip VARCHAR(255), logintime TIMESTAMP)

    E invece di accedere ai file, lavoriamo con il database.

    $errori = @mysql_result(mysql_query("SELECT count(username) as false FROM unauth WHERE logintime>DATE_SUB(NOW(),INTERVAL 1 HOUR) AND ip="$REMOTE_ADDR""),0); if (mysql_error()) die(mysql_error()); if ($errori>5) ( print ("L'accesso è chiuso. Torna tra un'ora."); exit(); ); $risultato = mysql_query("SELECT * FROM utente WHERE login="". preg_replace("/[^\w_\-]/", "", $PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW) """); if (@mysql_num_rows($risultato)!=1) ( header("WWW-Authenticate: Basic realm=\"area segreta\""); header("HTTP/1.0 401 Non autorizzato"); print ("Autorizzazione richiesta") ; mysql_query("INSERISCI IN VALORI unauth (nome utente, pass, ip) ("$PHP_AUTH_USER", "$PHP_AUTH_PW", "$REMOTE_ADDR $HTTP_X_FORWARDED_FOR")"); exit(); ); $utente_corrente = mysql_fetch_array($risultato); mysql_free_result($risultato);

    Se archiviare o meno i vecchi record per le statistiche è una decisione aziendale. Semmai possono essere cancellati eseguendo la seguente richiesta prima dell'autorizzazione:

    DELETE FROM unauth WHERE logintimeDATE_SUB(NOW(), INTERVAL 30 MINUTE)"); if (!mysql_error() && @mysql_num_rows($login_result)==1) ( /* Ottieni una riga della tabella e crea un hash dei campi richiesti. */ $ current_user = mysql_fetch_array($login_result); $hash_to_check = md5($current_user["passwd"]. "Y - quindi nessuno indovina." $current_user); if ($hash_to_check == $HTTP_COOKIE_VARS[$COOKIE_HASH_NAME]) ( $current_time = time(); /* Aggiorna il campo dell'ultimo accesso ed emette un nuovo cookie. */ mysql_query("UPDATE user SET last_log="". date("Y-m-d H:i:s", $current_time). " " WHERE login=" $login""); setcookie($COOKIE_HASH_NAME, md5(date("Y-m-d H:i:s", $current_time). "Y - in modo che nessuno indovini." $current_user["passwd"] ), $current_time + 1800 , $COOKIE_PATH); ) else ( /* Se l'hash non corrisponde, l'utente viene reindirizzato alla pagina di login. */ header ("Location: /login.php"); exit; ); ) elseif (!mysql_error() && @mysql_num_rows ($log_result)!=1) ( header("Posizione: /login.php"); Uscita; ) altrimenti stampa (mysql_error());

    Ovviamente "Y - in modo che nessuno indovini"È meglio separarlo anche in una variabile separata, ed è meglio utilizzare l’indirizzo IP del visitatore invece di questa riga (o, in caso di dialup interrotto, i primi due/tre numeri dell’indirizzo IP).

    A proposito, riguardo all'indirizzo IP. È meglio controllarlo, ma non l'intero indirizzo, ma solo i primi due (per IP che iniziano con un numero inferiore a 127) o tre (rispettivamente più di 127) numeri dell'indirizzo. Ciò eviterà agli utenti che hanno effettuato una connessione remota errata e interrotta di dover effettuare nuovamente l'accesso dopo che la connessione è stata persa e, allo stesso tempo, non consentirà a un utente malintenzionato che ha rubato il cookie di accedere. Ovviamente non potrà richiamare e accedere tramite un altro provider: l'indirizzo della piscina non è lo stesso, ma questo non è un nostro problema ("con questo tempo restano a casa"). Nemmeno il furto delle password all’interno dell’azienda è un nostro problema. Ci siamo protetti dai compagni curiosi e dagli hacker analfabeti, ma non possiamo fare nulla contro i trojan e gli sniffer che possono essere installati sulla vittima.

    Qui finiscono le “campane e fischietti”. La protezione non può essere resa più affidabile. Nessuno entrerà nel file dei cookie per prendere l'hash e lo preleverà. Sarebbe più semplice posizionare uno sniffer tra l'utente e l'interfaccia web e utilizzarlo per trovare la password. Puoi installare un Trojan che ricorderà tutto ciò che l'utente ha inserito sulla tastiera, ma questo non è più un nostro problema. Per proteggersi dalle intercettazioni dei canali, è necessario utilizzare connessioni SSL o crittografia dei dati.

    Password per la pagina. Parte 5. Sessioni

    Perché ho scritto una nota sui cookie? “Non capisco perché scrivere di cookie quando PHP ha sessioni?!” Quindi, in modo che i lettori non abbiano un'immagine piatta davanti agli occhi. Non ovunque esiste ancora la versione 4 di PHP e la versione 3 non è supportata. Inoltre, le sessioni non sono così necessarie ovunque: con rare eccezioni, l'algoritmo di autorizzazione controlla la correttezza del login/password e la correttezza dei dati della sessione, quindi riporta il client alla pagina di login o accetta un array (o oggetto ) con i dati sull'utente.

    I casi in cui è necessario lavorare in sessioni non sono così frequenti. Ad esempio, nel mio gioco "Monopolist" ho subito iniziato a utilizzare le sessioni, perché l'utente può giocare a più giochi e la stessa pagina nella stessa sessione può contenere dati diversi. Lì è meglio memorizzare i dati per uno dei giochi a cui l'utente partecipa alla sessione e creare una pagina per passare da un gioco all'altro.

    In generale, non sto dicendo che le sessioni non dovrebbero essere utilizzate. È necessario, ma ogni cosa ha il suo posto. Torneremo più avanti sulla questione dell'applicabilità dei tre metodi di autorizzazione: tramite l'intestazione 401 ("regno"), cookie o sessioni. Ora parliamo di sessioni.

    Le sessioni in PHP non sono effettivamente un metodo di autorizzazione (il concetto in sé è errato, ma nei forum si chiede esattamente “come autorizzare un utente tramite sessioni?”). Il meccanismo della sessione utente integrato in PHP identifica solo questi utenti; l'autorizzazione è, ancora una volta, opera del tuo script.

    Non ti dirò molto sul meccanismo delle sedute, è già stato detto. Nella sua forma più semplice (o meglio, nella sua forma più predefinita), questo meccanismo funziona così: il sistema mantiene sul server un file di sessione, che contiene le sue variabili. Quando avvia una sessione, l'utente riceve un identificatore univoco (solitamente tramite un cookie) e quando accede ad altre pagine lo invia. Quando avvii il meccanismo di sessione nel tuo script, il gestore php controlla se esiste un file corrispondente all'identificatore della sessione in entrata: se esiste, lo script sarà in grado di leggere i dati dal file, in caso contrario verrà avviata una nuova sessione e il file verrà creato. Naturalmente il nome di questa variabile è definito nelle impostazioni php.

    Ora su quali funzioni utilizziamo.

    inizio_session() . Avvia il meccanismo di sessione stesso. L'utente deve avere una variabile e un file corrispondente. Se non è presente alcun file, viene creato e la sessione viene avviata da zero. Se non sono presenti né un file né una variabile, viene generata una variabile (ad esempio, viene inviata un'intestazione con un cookie) e viene creato il file.

    session_register(nome1, nome2, nome3...) . Indicazione di quali variabili ricordare nel file alla fine dello script. Dopo che l'utente passa a un'altra pagina, è possibile avviare il meccanismo di sessione e, dopo aver chiamato questa funzione, le variabili saranno disponibili.

    sessione_distruggi() . Elimina il file dei dati della sessione (quando si utilizzano i cookie, è necessario eliminarli manualmente impostando un cookie vuoto: "setcookie(session_name())" ).

    session_set_cookie_params(vita, percorso, dominio) . Impostazione dei parametri dei cookie con un identificatore di sessione (per impostazione predefinita, il cookie è impostato sulla radice del server e per 0 secondi - fino alla chiusura del browser).

    È tutto per ora. Ci saranno questioni separate riguardo alle sessioni in dettaglio. Per ora descriverò il meccanismo di autorizzazione e identificazione dell'utente utilizzando le sessioni.

    Quindi, abbiamo tre file: login, verifica (auth) e output (logout).

    // elimina tutti i caratteri indesiderati $login = preg_replace("/[^\w_\.\-]/", "", $HTTP_POST_VARS["login"]); $passaggio = ritaglio($HTTP_POST_VARS["passaggio"]); // controllo delle variabili if (strlen($login)==0 || strlen($pass)==0) $error = "Inserisci login e password"; else ( // verifica login e password $user_result = mysql_query("SELECT * FROM user WHERE login="$login" AND pass="". md5($pass). """); /* se si è verificato un errore nel database (ad esempio, l'utente ha inserito una variabile lunga nella sessione, che il database non ha voluto digerire) o è risultata più di una riga, escludiamo l'utente */ if (mysql_error()) die(mysql_error()) ; elseif (@mysql_num_rows($user_result) != 1) $error = "Nome utente o password non validi."; // se tutto va bene, seleziona i dati, avvia la sessione else ( $user = mysql_fetch_assoc($user_result); session_set_cookie_params (1800, "/"); session_start() ; // ricorda i dati dell'utente session_register("user"); // e poi inviali da qualche parte if (isset($HTTP_POST_VARS["return"])) header("Location: ($HTTP_POST_VARS["return"]) "); else header("Posizione: /"); exit(); ); ); /* qui l'utente non è più autorizzato, ma può inviare un cookie da una sessione chiusa. puliamolo. */ if (isset($HTTP_COOKIE_VARS)) setcookie(session_name()); // poi disegniamo la forma, questo non è interessante.

    Questo script è sia un gestore che un modulo di immissione dati. Quando riceve login e password, li elabora e, se sono corretti, smette di funzionare, inviando l'utente alla pagina desiderata. Se i dati sono errati o mancanti, disegna il modulo.

    /* elimina la variabile utente in modo che dopo aver disegnato il modulo sia impossibile inviare dati in una richiesta post. */ unset($utente); // flag "errore di sessione": se è abilitato, il lavoro si interromperà. $errore_sessione = falso; // se non è presente alcun cookie con l'ID di sessione, attiva il flag if (!isset($HTTP_COOKIE_VARS)) $session_error = true; // se esiste, avvia il meccanismo di sessione e registra la variabile $user. else ( session_start(); session_register("user"); /* se per caso non ci sono login e password nell'array, anche il lavoro si ferma (“non sappiamo niente, te li abbiamo dati noi”) */ if (!isset($user[" login"]) || !isset($user["pass"])) $session_error = true; ); /* se finora l'utente è riuscito a evitare eroicamente gli errori, viene effettuato un controllo attraverso il database allo stesso modo dell'input. */ if (!$session_error) ( $check_result = mysql_query("SELECT uid FROM utente WHERE login="($user)" AND pass="($user)""); if (mysql_error() || @mysql_num_rows( $user_result) != 1) $session_error = true; ); // se si è verificato qualche errore, allora if ($session_error) ( // distruggi i dati della sessione session_destroy(); // distruggi il cookie se ce n'era uno if (!isset($HTTP_COOKIE_VARS)) setcookie(session_name()," " ,"/"); /* invia l'utente al login, con la possibilità di tornare all'indirizzo richiesto */ header("Location: /login.php?return=$REQUEST_URI"); // smette di funzionare exit() ; ); mysql_free_result($check_result);

    L'utente viene controllato e nell'array $user - tutti i dati su di lui, puoi, ad esempio, salutarlo con il suo nome e patronimico:

    If(isset($HTTP_COOKIE_VARS)) ( // avvia il meccanismo di sessione session_start(); // elimina il file session_destroy(); // elimina il cookie setcookie(session_name()); ); // esce dall'intestazione della pagina("Posizione: /login.php");

    Un paio di appunti: la parte protetta da password in questo esempio è l'intero server (ad esempio service.firm.ru), per chiudere la directory è necessario correggere i percorsi. Session_name() viene utilizzato al posto di PHPSESSID in modo che il nome dell'identificatore possa essere modificato liberamente. A proposito, su un server fisico puoi creare nomi diversi per gli identificatori di sessione: basta inserire il file .htaccess nella parte richiesta con la riga php_value session.name "ABRACADABRA" .




    Se hai altre domande o qualcosa non è chiaro, benvenuto nel ns

    Ho deciso di descrivere i modi per proteggere parte del sito con una password. L'argomento in realtà è piuttosto vasto, quindi per la prima volta mi limiterò all'autorizzazione php+mysql.

    La prima domanda che di solito sorge è come chiudere la directory con gli script di amministrazione con una password. In questo caso non sono necessari fronzoli: uno o più amministratori hanno gli stessi diritti e le personalità raramente cambiano. Il modo più semplice in questa situazione è utilizzare l'autorizzazione del server standard: inserire i file .htaccess e .htpasswd e scrivere in essi i parametri necessari. Molto è già stato scritto a riguardo, quindi non dirò nulla di particolarmente nuovo.

    Aggiungo due cose. Il primo è dove mettere il file .htpasswd. Sperimentalmente ho scoperto che se, ad esempio, il percorso di un documento con un messaggio di errore (ErrorDocument) viene scritto rispetto alla variabile di sistema DocumentRoot. Ma il percorso del file della password (UserFile) è scritto rispetto a ServerRoot. Per quanto ho capito, non puoi inserire .htpasswd sopra ServerRoot - "../" non viene percepito. Tutto ciò viene fatto in modo che sia possibile posizionare un file con password, ad esempio, un livello sopra la directory principale del sito, in modo che non vi sia alcun accesso al file dalla rete.

    La seconda è che lo script possa scoprire chi lo sta aprendo e la password: le variabili $PHP_AUTH_USER e $PHP_AUTH_PW.

    Lo svantaggio principale di questo metodo è che il server non può bloccare l'ipotesi della password (dopo diversi tentativi di accesso falliti, all'utente viene chiesto di attendere un'ora o due e durante questo periodo le chiamate dal suo indirizzo IP vengono ignorate). Questo è scritto nella documentazione ufficiale di Apache.

    Un altro inconveniente è la necessità di riscrivere i file con le password quando si elimina un utente o se ne introduce uno nuovo. Ma se ciò accade raramente, questo metodo è più che sufficiente e non dovrai preoccuparti di scrivere un meccanismo di autorizzazione.

    Automazione dell'autorizzazione

    Ciò è necessario non solo per semplificare il lavoro con un gran numero di utenti e il loro elevato turnover. Se è necessario conservare informazioni aggiuntive sugli utenti o se è necessaria una differenziazione flessibile dei diritti, è meglio trasferire l'autorizzazione al database.

    Ogni pagina di un territorio chiuso include un file con il seguente codice:

    $risultato = mysql_query(" SELECT * FROM persona WHERE login="". preg_replace("/[^w_-]/","",$PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW). " ""); if (@mysql_num_rows($result)!=1) ( header("WWW-Authenticate: Basic realm="Area utente""); header("HTTP/1.0 401 Non autorizzato"); print("Per accedere all'area utente del sito, è necessario inserire nome utente e password."); exit(); ); $riga_utente = mysql_fetch_array($risultato);

    Nella prima riga, tutti i caratteri tranne lettere, numeri, trattini e trattini bassi vengono rimossi dal login. Viene quindi controllato il numero di righe ricevute e solo se si tratta di una riga viene concesso l'accesso. In altri casi, l'utente vedrà una finestra nel browser che richiede di inserire login e password. Se l'utente ha effettuato l'accesso con successo, abbiamo tutte le informazioni su di lui nell'array $user_row.

    Naturalmente, l’esempio che ho fornito presenta una serie di carenze significative. Non riscriverlo uno a uno, per non cadere vittima di tentativi di indovinare la password, perché
    1. qui non esiste alcuna protezione contro la selezione
    2. se la tabella utente è grande, quando indovina la password, molto probabilmente un utente malintenzionato travolgerà il database

    E l'ultimo metodo per oggi è archiviare dati crittografati nei cookie.

    C'è uno script per l'accesso, il resto include un codice che ti consente di continuare le azioni solo in un'area chiusa: se i cookie scadono o si disconnette da lì, dovrai tornare alla pagina di accesso.

    Lo script di input controlla il login e la password ed emette due cookie. Nel primo - il login, per identificare immediatamente l'utente (nel database il campo login è, ovviamente, unico o addirittura chiave). Il secondo cookie contiene l'hash dell'ora di accesso e della password (per completezza di segretezza, aggiungo la lettera "Y" a queste righe - quindi è quasi impossibile trovare l'hash :).

    Tutti gli altri programmi includono codice che esegue le seguenti operazioni. Effettua una richiesta al database: seleziona la riga con il login ricevuto. Da questa riga prende il campo “log_time” e la password e ne crea un hash, come descritto sopra. Lo confronta con quello che ha ricevuto e, se corrispondono, emette un nuovo cookie hash, ancora una volta, dalla password, dall'ora e dalla lettera "Y" e fa una query al database "UPDATE utente SET log_time='...' WHERE login ='$cookie_login'".

    if (isset($HTTP_COOKIE_VARS[$cookie_login]) && isset($HTTP_COOKIE_VARS[$cookie_code])) ( $login = $HTTP_COOKIE_VARS[$cookie_login]; $code = $HTTP_COOKIE_VARS[$cookie_code]; $risultato = mysql_query("SELECT date_format(log_date,"%Y%m%d%H%i%s") come log_date1,pass,uid DALL'utente DOVE email="$login" E log_date>"DATA_SUB(ORA(),INTERVALLO 15 MINUTI)"" ); if (!mysql_error() && @mysql_num_rows($risultato)==1) ( $log_time0 = ora(); $log_time1 = date("YmdHis", $log_time0); $log_time2 = date("Y-m-d H:i :s", $log_time0); $current_user = mysql_fetch_array($result); if (md5($current_user["pass"].$current_user["log_date1"].$md5letter) == $code) ( mysql_query("AGGIORNA utente SET log_date="$log_time2" WHERE uid=".$current_user["uid"]); setcookie($cookie_code, md5($current_user["pass"].$log_time1.$md5lettera), ora()+900, $percorso_sito); $auth = true; ) altrimenti unset($current_user); ); );

    Ancora una volta, qui non c'è protezione dalla selezione e dall'attacco al server (a proposito, qui puoi scrivere l'indirizzo IP dell'utente invece della lettera "Y" - in modo che, ad esempio, un vicino di ufficio non possa prendere un file con un cookie ed effettuare l'accesso dal suo computer).

    Password per la pagina. Parte 2. Blocco delle assunzioni

    Quando ho postato questo problema l'ultima volta, mi hanno preso a calci sul posto, dicendo che un blocco del genere avrebbe potuto far deragliare il server.

    Ma prima parliamo del blocco del rimbalzo. Banalità, ma comunque. Una password di dieci caratteri composta da lettere latine e numeri significa che ci sono molte opzioni. Se indovini una password 1.000.000 di volte al secondo, ci vorranno diverse migliaia di anni. Ma poiché queste parole incomprensibili sono difficili da ricordare, spesso creiamo password con parole significative. Alcuni anni fa si è scoperto che la maggior parte delle password può essere indovinata utilizzando un dizionario di 10.000 parole. Un tempo, sulla rete apparve un worm (un virus del genere) che si insinuò nei server Unix, sfruttando le loro falle di sicurezza, e raccolse password per utenti privilegiati utilizzando... il dizionario ortografico del sistema Unix. Non c'era bisogno di portare nulla!

    Ogni utente, finché non ha inserito login e password corretti, è considerato un hacker malvagio. Di cosa ci occupiamo quando l'utente inserisce qualcosa in modo errato?
    dimenticanza (per questo i siti decenti dispongono di un modulo “password dimenticata” per inviare la stessa password all'e-mail inserita nelle impostazioni di sistema)
    coccole (“perché non mi interessa”)
    selezione della password tramite dizionario (la probabilità di una selezione riuscita è alta, quindi è necessario chiuderla, soprattutto se il sito è di natura commerciale)
    Attacco DoS (per non sovraccaricare il server è necessario ridurre al minimo le azioni che lo script eseguirà in questo caso)

    Ho pensato a lungo a come potrei causare un sovraccarico sul server se il meccanismo di protezione si basa sui file. Si è rivelato facile (quanto costerà è un'altra domanda). Quindi, diciamo che il server non sarà in grado di gestirlo se lo script tenta di aprire file in scrittura 1000 volte al secondo e di scrivervi dati. Poiché dopo 5 tentativi di accesso falliti, all'utente verrà immediatamente negato l'accesso (senza che alcun dato venga scritto nel file), è necessario trovare 200 IP univoci, dai quali è necessario contattare cinque volte ciascuno. E' possibile. Appendiamo un banner html con cinque tag nello scroller del banner:

    L'utente effettua immediatamente cinque richieste, il server scrive sul file cinque volte (a proposito, in alcuni browser potrebbe apparire una finestra per l'inserimento di login e password). Puoi creare una pagina HTML con cinque di queste immagini e inserire la pagina stessa tramite un iframe nel sito che stai visitando (tramite un iframe - in modo che il campo referer non venga trovato. È improbabile che il servizio di supporto di un servizio gratuito l'hosting si occuperà di cose come scavare nei file di registro alla ricerca di referrer). Gli esempi che ho fornito sono, ovviamente, inverosimili, ma è dimostrato il fatto stesso che si possa trarre vantaggio da un simile difetto del sistema. A proposito, qualcosa di simile è già successo.

    Ma ti darò comunque questo metodo: l'ho scritto invano, o cosa? A proposito, può essere utilizzato senza troppi timori per un numero limitato di indirizzi (ad esempio, per la rete locale di un'azienda) inserendo nella directory un file .htaccess con il seguente contenuto:

    ordine nega, consenti
    negare da tutti
    consentire da xxx.xxx.xxx

    Ed ecco il codice del programma:

    $errori = 0; $fn = "ignora/". preg_replace("[^d.]", "", $REMOTE_ADDR. ".". $HTTP_FORWARDED_FOR); if (is_file($fn)) ( if (filectime($fn)< time()-3600) unlink($fn); else $errors = fread(fopen($fn, "r"), 2); }; if ($errors>5) ( print ("L'accesso è chiuso. Torna tra un'ora."); exit(); ); // qui viene stabilita la connessione con il server del database. per non toccarsi invano se l'utilizzatore viene subito “picchiato”. $risultato = mysql_query("SELECT * FROM utente WHERE login="". preg_replace("/[^w_-]/", "", $PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW). " ""); if (@mysql_num_rows($risultato)!=1) ( header("WWW-Authenticate: Basic realm="area segreta""); header("HTTP/1.0 401 Non autorizzato"); print ("Autorizzazione richiesta"); fwrite (fopen($fn, "w"), ++$errori); exit(); ); $utente_corrente = mysql_fetch_array($risultato); mysql_free_result($risultato); Tuttavia, è un peccato lavorare con i file se è presente un database. Scherzo. Per le autorizzazioni fallite, creiamo una tabella: CREATE TABLE unauth (username VARCHAR(64) NOT NULL, pass VARCHAR(64) NOT NULL, ip VARCHAR(255), logintime TIMESTAMP) E invece di accedere ai file, lavoriamo con il database. $errori = @mysql_result(mysql_query("SELECT count(username) as false FROM unauth WHERE logintime>DATE_SUB(NOW(),INTERVAL 1 HOUR) AND ip="$REMOTE_ADDR""),0); if (mysql_error()) die(mysql_error()); if ($errori>5) ( print ("L'accesso è chiuso. Torna tra un'ora."); exit(); ); $risultato = mysql_query("SELECT * FROM utente WHERE login="". preg_replace("/[^w_-]/", "", $PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW). " ""); if (@mysql_num_rows($risultato)!=1) ( header("WWW-Authenticate: Basic realm="area segreta""); header("HTTP/1.0 401 Non autorizzato"); print ("Autorizzazione richiesta"); mysql_query ("INSERT INTO unauth (nome utente, pass, ip) VALUES ("$PHP_AUTH_USER", "$PHP_AUTH_PW", "$REMOTE_ADDR $HTTP_X_FORWARDED_FOR")"); exit(); ); $utente_corrente = mysql_fetch_array($risultato); mysql_free_result($risultato);

    Se archiviare o meno i vecchi record per le statistiche è una decisione aziendale. Semmai possono essere cancellati eseguendo la seguente richiesta prima dell'autorizzazione:

    ELIMINA DA unauth DOVE logintime