Login e Riconoscimento [Problema]
Login e Riconoscimento [Problema] postato il 17/08/2011 09:34:14 nel forum programmazione, open source e hosting
Ciau a tutti, vediamo se qualche anima pia ha la bontà ma anche tanta pazienza (Perché aimè sono alle prime armi quindi devo imparare e molto) di aiutarmi a capire una cosa… Dunque sarò molto, spero, precisa. Io ho un modulo di login semplice semplice dove inserisco NICK e PASS (Ancora non criptata) e mi invia tutto a una pagina di controllo php dove verifico e avvio una sessione, vi faccio vedere:
<?php
require_once("config.php"); //mi connetto al db selezionato
$giorno=date('j');
$mese=date('M');
if($mese=="Jan"){$meseOK="Gennaio";}
if($mese=="Feb"){$meseOK="Febbraio";}
if($mese=="Mar"){$meseOK="Marzo";}
if($mese=="Apr"){$meseOK="Aprile";}
if($mese=="May"){$meseOK="Maggio";}
if($mese=="Jun"){$meseOK="Giugno";}
if($mese=="Jul"){$meseOK="Luglio";}
if($mese=="Aug"){$meseOK="Agosto";}
if($mese=="Sep"){$meseOK="Settembre";}
if($mese=="Oct"){$meseOK="Ottobre";}
if($mese=="Nov"){$meseOK="Novembre";}
if($mese=="Dec"){$meseOK="Dicembre";}
$ora=date('H:i');
$anno=date('Y');
$data="$giorno"." $meseOK"." $anno"." $ora";
$data2="$giorno"." $meseOK"." $anno"." $ora";//Calcolo la data testuale
$pg=$_POST['pg'];
$pass=$_POST['pass'];
$control1=mysql_query("SELECT * FROM user WHERE nome='".$pg."' AND password='".$pass."'");//selezione utente da db
$pgnum=mysql_num_rows($control1);
$control=mysql_fetch_assoc($control1);
$ip=$_SERVER["REMOTE_ADDR"]; //recupero l'ip
if($pgnum!='1'){ //controllo se il pg esiste
header("Location: php_errori/utente_inesistente.php");
exit();
}
if($control[ban]=='1'){
header("Location: php_errori/utente_bannato.php");
exit();
}
if($control[connesso]=='1'){
header("Location: php_errori/utente_collegato.php");
exit();
}
if(($ip==$control['ip']) OR ($control['connesso']=='0')){
session_start();
$_SESSION['nome'] = $control['nome'];
$user = mysql_real_escape_string($_POST['pg']);
$user = htmlentities ($_POST['pg']);
$pass = mysql_real_escape_string($_POST['pass']);
$pass = htmlentities ($_POST['pass']);
$user=$_SESSION['nome'];
$now=time();//recupero time
$insert=mysql_query("INSERT INTO accessi (nome,data,data2,ip,stato) VALUES ('".$user."','".$data."',NOW(),'".$ip."','entrato')");//inserisci accesso
$update=mysql_query("UPDATE user SET time='".$now."', luogo='Mappa', luogo_a='Mappa', ullacc='".$data2."', connesso='1', ip='".$ip."', ultimaexp = '".$now."' WHERE nome='".$user."'");//aggiorno valori
header('Location: gioco.php', true);//mando la prima pagina
}
?>
Bene una volta fatto questo controllo SE l’utente non è collegato/bannato/inesistente mi fa andare alla pagina gioco.php quindi mi farà passare il login e mi manderà alla pagina interna dove ci sarà, per ogni pagina, un controllo del genere per la sessione e la validità dell’utente posto in cima a tutto:
<?php
session_start();
require_once(config.php');
if(isset($_SESSION['nome']) && !empty($_SESSION['nome'])){
$row=mysql_fetch_array(mysql_query("SELECT * FROM user WHERE nome='".$_SESSION['nome']."'"));
….?>
Ora il problema dov’è che sta, su Altervista (Eh già sono li al momento) se imposto PHP 4 il gioco funziona magnificamente quindi mi fa utilizzare tutto e mi fa vedere tutto, ma se magicamente vado a impostare il PHP 5 attivo i problemi sono tre:
1) Mi fa accedere però non mi carica il LUOGO dell’utente, quindi di conseguenza non mi fa vedere nemmeno i menu di navigazione per le Chat;
2) Quando clicco sul pulsante per il collegamento alla Scheda del PG non me la fa vedere, né il mio né quello degli altri;
3) Non mi scrive in Chat, come se l’input dell’utente non fosse presente nella sessione;
però tutto il resto funziona come se ci fosse impostato il PHP 4, com’è possibile?
Non chiedo rapide soluzioni, anche se sarebbero ben accettate ghghg scherzi a parte, però una mano a capire dove potrebbe stare l’errore mi farebbe comodo.
17/08/2011 10:03:52 e modificato da blancks il 17/08/2011 10:04:35
marziafantasy ha scritto:
1) Mi fa accedere però non mi carica il LUOGO dell’utente, quindi di conseguenza non mi fa vedere nemmeno i menu di navigazione per le Chat;
2) Quando clicco sul pulsante per il collegamento alla Scheda del PG non me la fa vedere, né il mio né quello degli altri;
3) Non mi scrive in Chat, come se l’input dell’utente non fosse presente nella sessione;
Ho dato una sbirciata al codice e mi pare di capire che lo script del login è l'unico che non ti crea problemi.
Mi vien dunque da pensare che non abbiamo molti elementi per aiutarti a capire di cosa si tratta visto che, il luogo dell'utente non mi pare venga recuperato da qui, il collegamento della scheda del PG suppongo sia anch'esso in una procedura differente e idem per la chat.
A intuito, mi vien da pensare che il problema possano essere le globals, ovvero potresti aver usato i riferimenti di sessione sottoforma di variabili, una pratica che in php5 è stata dichiarata deprecata e quindi disattivata perchè pieno di rischi per la sicurezza.
Pertanto, se non lo hai già fatto, specifica esplicitamente ogni variabile di sessione usando l'apposito array superglobale $_SESSION.
Quanto al fatto che sei in fase di apprendimento ti lascio qualche consiglio ;-)
- E' convenzione che il session_start() sia la prima o una delle prime istruzioni presenti nello script, subito dopo la prima apertura dell'area di lavoro di php ( <?php ), questo perchè se viene tirato fuori un qualsiasi tipo di output prima del session_start la funzione restituisce un errore di tipo E_WARNING in quanto funziona restituendo al browser degli header.
- Nella serie iniziale di if atti alla verifica e alla sostituzione della nomenclatura del mese col corrispettivo in lingua italiana, potrebbe tornarti più pratico l'uso di uno switch ;-)
- Nella prima query per l'identificazione del personaggio passi gli input utente non filtrati direttamente nella query SQL, sei così facilmente vulnerabile a injenction.
- Ho visto alcune chiavi di un array richiamate senza l'uso degli apici. E' importante inserirli sempre.
- Ho visto un header che non è seguito da un exit/die per arrestare l'esecuzione dello script. L'header invia al browser una richiesta di redirect ed è questo che è tenuto a farvi fede, per tal motivo non si può dare per assodato che venga eseguito quindi termina sempre l'esecuzione dello script dopo un redirect.
- Gli errori di MySql prodotti da un errata sintassi dalle query SQL non sono normalmente visibili in php, puoi però invocarli ricorrendo all'applicazione del seguente metodo.
mysql_query(..)or die(mysql_error());
17/08/2011 10:21:34
Dunque io ne famoso codice che richiamo in ogni pagina c’è un require_once che mi include la pagina di sessione ovvero il codice che mi inizializza o riprende la sessione, ecco qui:
<?php
session_start();
$user = $_SESSION['nome'];
?>
Non so se era questo che volevi sapere. Quanto ai suggerimenti dati ti rispondo in ordine:
1) Si, session_start(); è sopra di tutto non c’è assolutamente nulla prima;
2) Modifico subito, era una cosa che volevo fare e farò a breve, ti ringrazio del suggerimento utile;
3) Mi conviene quindi passarli per mysql_real_escape_string giusto?
4) nel modulo di controllo giusto?
5) Quindi, scusa se sono ripetitiva, in pratica dopo un reindirizzamento devo sempre chiudere il tutto con exti(); o die (mysql_ecc ecc)?
6) Mi consigli quindi per ogni query di completare il tutto con l’informativa di eventual errore, giusto?
17/08/2011 10:32:43
marziafantasy ha scritto:
Dunque io ne famoso codice che richiamo in ogni pagina c’è un require_once che mi include la pagina di sessione ovvero il codice che mi inizializza o riprende la sessione, ecco qui:
<?php
session_start();
$user = $_SESSION['nome'];
?>
Non so se era questo che volevi sapere. Quanto ai suggerimenti dati ti rispondo in ordine:
Se tutti i dati di sessione sono recuperati come nell'esempio allora dovrebbe essere a posto, converrebbe magari vedere il sorgente della pagina in cui c'è il link alla scheda del personaggio a questo punto ;-)
1) Si, session_start(); è sopra di tutto non c’è assolutamente nulla prima;
Parlo nella pagina postata qui sul forum, quella del login insomma.
3) Mi conviene quindi passarli per mysql_real_escape_string giusto?
Se sai che non ammetti neanche i caratteri speciali nei nickname degli utenti puoi usare anche htmlentities http://php.net/htmlentities ↗ settando il parametro opzionale su ENT_QUOTES.
4) nel modulo di controllo giusto?
Ovunque richiami degli array specificando delle chiavi e ti accorgi di aver tralasciato gli apici, tipo qui:
$control[ban]
5) Quindi, scusa se sono ripetitiva, in pratica dopo un reindirizzamento devo sempre chiudere il tutto con exti(); o die (mysql_ecc ecc)?
die/exit e mysql_error sono due funzioni differenti, nella tecnica usata per visualizzare gli errori delle query si usano insieme poichè torna utile arrestare lo script nel punto dove si trova la query in cui è sorto l'errore
In sostanza, basta solo usare die() o exit() dopo un redirect, come hai già fatto anche in alcuni.
6) Mi consigli quindi per ogni query di completare il tutto con l’informativa di eventual errore, giusto?
Sicuramente è utile per il debug e per errori che altrimenti non vedresti mai perchè rimangono nel gestore del database.
Ti confesso comunque che non è il metodo migliore, ma al momento ti serve per fare esperienza: quando ne avrai acquisita di più lo capirai anche da sola ;-)
17/08/2011 10:39:35
1) Si, io in ogni pagina recupero tramite require_once(‘pagina_di_sessione.php’); ad esempio e dentro quella pagina c’è il codice
<?php
session_start();
$user = $_SESSION['nome'];
?>
per cui credo il problema non dovrebbe essere questo, a meno che l’errore non sia questo ovvero la variabile $user cioè mi spiego, se io facessi così:
<?php
session_start();
$_SESSION = $user['nome'];
?>
è sbagliata?
2) Sistemo subito e provo;
3) Si, vorrei inibire anche quelli giusto per sicurezza;
4) Sistemo subito anche questo;
5) Meglio die o exit a questo punto, poiché io ho messo exit però non vorrei ci fossero differenze particolari su i due, per gli header;
6) Perfetto!
17/08/2011 10:52:58 e modificato da blancks il 17/08/2011 10:57:42
marziafantasy ha scritto: 1) Si, io in ogni pagina recupero tramite require_once(‘pagina_di_sessione.php’); ad esempio e dentro quella pagina c’è il codice
<?php
session_start();
$user = $_SESSION['nome'];
?>
per cui credo il problema non dovrebbe essere questo, a meno che l’errore non sia questo ovvero la variabile $user cioè mi spiego, se io facessi così:
<?php
session_start();
$_SESSION = $user['nome'];
?>
è sbagliata?
Si, decisamente poiché in questo modo stai riscrivendo tutto $_SESSION e perdi quindi le informazioni archiviateci.
Secondariamente $user non viene valorizzato da nessun altra parte, per cui il secondo caso non ha senso logicamente parlando ai fini dello script.
5) Meglio die o exit a questo punto, poiché io ho messo exit però non vorrei ci fossero differenze particolari su i due, per gli header;
Prendi sempre in esame la referenza ufficiale di php.net, li c'è scritto quasi sempre tutto ciò che occorre sapere su ogni funzione del core o di eventuali moduli presenti in PHP.
Per die http://php.net/die ↗ in particolare ti cito:
"die — Equivalent to exit()"
Per cui non c'è nessunissima differenza tra i due ;-)
17/08/2011 13:46:35
Ciao ^^
blanks ha risposto alla maggior parte delle cose, volevo solo aggiungere un paio di particolari che mi sono spuntati in mente:
Invece di convertire i mesi manualmente con una serie di if o uno switch potresti sfruttare il fatto che PHP può già darteli correttamente in italiano, basta dirgli che li vuoi così ;)
setlocale(LC_TIME, 'ita', 'it_IT');//impostazione per le date in italiano
$data=strftime("%e %B %Y %S");//questa è l'equivalente di date(), ma ti stampa le cose in italiano
per ulteriori info consulta il manuale di PHP
http://it.php.net/manual/en/function.setlocale.php ↗
http://it.php.net/manual/en/function.strftime.php ↗
Questo ha poco senso:
$_SESSION['nome'] = $control['nome'];
$user = mysql_real_escape_string($_POST['pg']);
$user = htmlentities ($_POST['pg']);
$pass = mysql_real_escape_string($_POST['pass']);
$pass = htmlentities ($_POST['pass']);
$user=$_SESSION['nome'];
Stai continuando a sovrascrivere il valore di $user e $pass. Alla fine ti risulta $user=$control['nome'], che quindi non è reso sicuro per la query.
htmlentities non dovrebbe essere usato per inserire dati nel database, va usato dopo averceli estratti e prima di stamparli a schermo. Prova così:
$_SESSION['nome'] = $control['nome'];
$user = mysql_real_escape_string($_POST['pg']);
$pass = mysql_real_escape_string($_POST['pass']);
Io non utilizzerei htmlentities per codificare i nomi degli utenti nel database, perchè non sai mai dove potresti avere bisogno di mettere quel nome, magari da qualche parte dove non dovrebbe essere codificato con le entità HTML. Io consiglio mysql_real_escape_string per inserirlo nel database, e solo quando estrai il nome dal DB gli applichi htmlentities per stamparlo a schermo.
if(($ip==$control['ip']) OR ($control['connesso']=='0'))
In questo caso non dovresti incontrare problemi, ma stai molto attenta quando usi 'or' oppure 'and', perchè in PHP sono operatori logici cortocircuitati. Significa che se hai:
A or B
se A è vero l'operazione di or ritorna immediatamente vero senza controllare il valore di B. (duale per 'and') Questa cosa può andare bene se stai facendo un if con sole variabili nella condizione, ma se invece ci sono delle funzioni da eseguire potrebbero non venire eseguite.
è sempre consigliabile usare '||' e '&&' invece di 'or' e 'and' a meno che non ti serva esplicitamente che l'operatore logico faccia un cortocircuito.
18/08/2011 08:15:49
Buongiorno a tutti, scusate se ieri non ho risposto più ma mi son messa di buona intenzione a sistemare gli errori che gentilmente Blancks mi ha segnalato poi in privato e a quanto pare ho costruito un codice su un quadro PHP 4 e non PHP 5, grazie a lui ora sto provvedendo a modificare tutto in modo che dopo si spera funzioni comunque vi terrò aggiornati in merito ^__^
Ciao leoblacksoul ^___^ Ti ringrazio, provvederò a modificare quanto detto e vediamo come viene fuori, sono molto curiosa, grazie moltissimo sul serio.
18/08/2011 11:04:43
Ho modificato la pagina main.php così:
<?php
session_start();
require_once("collegamento al db"); //connessione al db
setlocale(LC_TIME, 'ita', 'it_IT');//impostazione per le date in italiano
$data=strftime("%e %B %Y %S");//questa è l'equivalente di date(), ma ti stampa le cose in italiano
$data2=strftime("%e %B %Y %S");//questa è l'equivalente di date(), ma ti stampa le cose in italiano
$pg = mysql_real_escape_string($_POST['pg']);
$pass = mysql_real_escape_string($_POST['pass']);
$pg=$_POST['pg'];
$pass=$_POST['pass'];
$pass=sha1($pass);
$control1=mysql_query("SELECT * FROM user WHERE nome='".$pg."' AND password='".$pass."'");//selezione utente da db
echo "SELECT * FROM user WHERE nome='".$pg."' AND password='".$pass."'";
die();
$pgnum=mysql_num_rows($control1);
$control=mysql_fetch_assoc($control1);
$ip=$_SERVER["REMOTE_ADDR"]; //recupero l'ip
if($pgnum!='1'){
header("Location: utente_inesistente.php");
exit();
}
if($control['ban']=='1'){
header("Location: utente_bannato.php");
exit();
}
if($control['connesso']=='1'){
header("Location: utente_collegato.php");
exit();
}
if(($ip==$control['ip']) OR ($control['connesso']=='0')){
session_start();
$_SESSION['nome'] = $control['nome'];
$user = mysql_real_escape_string($_POST['pg']);
$pass = mysql_real_escape_string($_POST['pass']);
$user=$_SESSION['nome'];
$now=time();//recupero time
$insert=mysql_query("INSERT INTO accessi (nome,data,data2,ip,stato) VALUES ('".$user."','".$data."',NOW(),'".$ip."','entrato')");//inserisci accesso
$update=mysql_query("UPDATE user SET time='".$now."', luogo='Mappa', luogo_a='Mappa', ullacc='".$data2."', connesso='1', ip='".$ip."', ultimaexp = '".$now."' WHERE nome='".$user."'");//aggiorno valori
header('Location: main2.php', true);//mando la prima pagina
}
?>
Va bene?
18/08/2011 12:44:09 e modificato da leoblacksoul il 18/08/2011 12:47:13
Va meglio, ma ci sono ancora degli errori:
$data=strftime("%e %B %Y %S");//questa è l'equivalente di date(), ma ti stampa le cose in italiano
$data2=strftime("%e %B %Y %S");//questa è l'equivalente di date(), ma ti stampa le cose in italiano
perchè ci sono due date? contengono esattamente lo stesso valore quindi mi sembra che sia inutile averne due uguali.
$pg = mysql_real_escape_string($_POST['pg']);
$pass = mysql_real_escape_string($_POST['pass']);
$pg=$_POST['pg'];
$pass=$_POST['pass'];
$pass=sha1($pass);
Ricorda che quando fai un assegnazione di un valore in una variabile sovrascrivi completamente quello che ci avevi messo dentro in precedenza, le operazioni non si sommano insieme magicamente. In questo caso prima fai l'escape, ma poi cancelli completamente quello che avevi fatto e rimetti $pg con il valore del $_POST e $pass con una password criptata tramite sha1. Consiglio: ricordati che sia l'escape per il database, sia la conversione delle entità HTML è quasi sempre l'ultima cosa da fare. Prima si fanno tutte le elaborazioni, e solo alla fine prima in inserire la stringa nella query fai l'escape, altrimenti può risultare inutile. Stessa cosa per la conversione delle entità HTML con htmlentities, sempre l'ultima cosa prima di usare echo. Così è corretto:
$pg = mysql_real_escape_string($_POST['pg']);
$pass = mysql_real_escape_string(sha1($_POST['pass']));
echo "SELECT * FROM user WHERE nome='".$pg."' AND password='".$pass."'";
die();
Attenzione, qui il tuo script si ferma inesorabilmente e non riuscirai mai a fare login: hai chiamato die() senza metterlo dentro a nessun if. Ricorda che quando chiami exit() o die() stai dicendo allo script di bloccarsi e terminare. Se metti una di queste due funzioni libera nel codice senza metterle attorno un if o una qualche condizione, verrà eseguita sempre; cioè il tuo script non arriverà mai alla fine. Non so cosa tu volessi fare in questo punto, probabilmente un controllo degli errori di Mysql? Allora dovrebbe essere cosi:
$query="SELECT * FROM user WHERE nome='".$pg."' AND password='".$pass."'";
$control1=mysql_query($query) or die($query." ha prodotto errori: ".mysql_error());//selezione utente da db
$_SESSION['nome'] = $control['nome'];
$user = mysql_real_escape_string($_POST['pg']);
$pass = mysql_real_escape_string($_POST['pass']);
$user=$_SESSION['nome'];
Stessa cosa di sopra, stai sovrascrivendo i valori di $user. Correzione:
$_SESSION['nome'] = $control['nome'];
$user = mysql_real_escape_string($control['nome']);
Ho tolto l'escape della password perchè era inutile, dato che nel codice successivo non lo usi.
18/08/2011 14:34:29
Capito, quindi in pratica io non facevo altro che sovrascrivere i dati che prima filtravo con mysql_real_escape_string e/o altri input precedenti, giusto?
adesso ho messo così:
<?php
session_start();
require_once("connessione al db"); //connessione al db
setlocale(LC_TIME, 'ita', 'it_IT');//impostazione per le date in italiano
$data=strftime("%e %B %Y %S");//questa è l'equivalente di date(), ma ti stampa le cose in italiano
$pg = mysql_real_escape_string($_POST['pg']);
$pass = mysql_real_escape_string(sha1($_POST['pass']));
$query= "SELECT * FROM user WHERE nome='".$pg."' AND password='".$pass."'";
$control1=mysql_query($query) or die($query." ha prodotto errori: ".mysql_error()); //selezione utente da db
$pgnum=mysql_num_rows($control1);
$control=mysql_fetch_assoc($control1);
$ip=$_SERVER["REMOTE_ADDR"]; //recupero l'ip
if($pgnum!='1'){ //controllo se il pg esiste
header("Location: php_errori/utente_inesistente.php");
exit();
}
if($control['ban']=='1'){
header("Location: php_errori/utente_bannato.php");
exit();
}
if($control['connesso']=='1'){
header("Location: php_errori/utente_collegato.php");
exit();
}
if(($ip==$control['ip']) OR ($control['connesso']=='0')){
session_start();
$_SESSION['nome'] = $control['nome'];
$user = mysql_real_escape_string($control['nome']);
$now=time();//recupero time
$insert=mysql_query("INSERT INTO accessi (nome,data,data2,ip,stato) VALUES ('".$user."','".$data."',NOW(),'".$ip."','entrato')");//inserisci accesso
$update=mysql_query("UPDATE user SET time='".$now."', luogo='Mappa', luogo_a='Mappa', ullacc='".$data."', connesso='1', ip='".$ip."', ultimaexp = '".$now."' WHERE nome='".$user."'");//aggiorno valori
header('Location: main2.php', true);//mando la prima pagina
}
?>
Discussione seguita da
Rispondi alla Discussione Segui Discussione Inoltra Discussione Forum Programmazione, Open Source e Hosting Elenco Forum
Articoli, Interviste e altre Risorse!
World of Tanks ↗
World of Warship ↗
RAID Shadow Legends ↗
Foundation Galactic Frontier ↗
War Thunder ↗
Fallen Gods ↗
Raja Dunia ↗
CRSED: F.O.A.D. ↗
Sea of Conquest ↗