Guida [GUIDA] Login System con WWW

Stato
Discussione chiusa ad ulteriori risposte.

ManHunter

Utente Jade
14 Settembre 2009
985
111
780
818
Ultima modifica da un moderatore:
Salve,
durante la realizzazione del mio progetto (a breve un'anteprima), mi sono imbattuto nella creazione di un sistema di autenticazione degli utenti. Dal momento che la prima versione risultava scadente in termini di sicurezza dei dati, dopo qualche ricerca ho trovato un metodo interessante che fa uso della classe WWW.
E' molto facile da comprendere e da realizzare, quindi passo subito al sodo. ;)


La guida fa uso di linguaggi di scripting come il PHP e linguaggi di modellazione dati come l'SQL. Per domande riguardanti tali linguaggi, vi invito a consultare dapprima i link alle varie documentazioni che vi ho allegato sopra e poi a porre qui i vostri dubbi.


Innanzitutto, avremo bisogno di un database e di una tabella. Potete utilizzare qualsiasi DBMS, in questo caso verrà utilizzato MySQL (questo non esclude che voi possiate utilizzarne altri come PostgreSQL, SQLServer, ecc).


Create il vostro database o utilizzatene uno che avete già creato.
Create la vostra tabella che, per semplicità, in questa guida chiamerò "Account".


PHP:
CREATE TABLE `Account` (`AccountID` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,`AccountName` VARCHAR(30) NOT NULL,`Password` VARCHAR(32) NOT NULL,`Email` VARCHAR(50) NOT NULL,`DataCreazione` DATETIME NOT NULL,`StatoAccount` VARCHAR(10) NOT NULL DEFAULT 'OK',) ENGINE = innodb;


Personalizzate la tabella come meglio credete, questi sono solo alcuni campi che ho utilizzato io, potete aggiungere molte altre cosette, avendo ovviamente cura di aggiungere eventuali campi aggiuntivi nei vari script.


Abbiamo ora la nostra tabella, la quale conterrà i dati degli account registrati. Inseriamo subito un account:


PHP:
INSERT INTO `Account` ( `AccountName` , `Password`, `Email`, `DataCreazione` )VALUES ( 'prova', MD5( 'prova123' ), '[email protected]', NOW() );


Abbiamo così creato un nuovo account che useremo per le nostre prove. Potete, ovviamente, creare qualche pagina PHP per un inserimento più immediato di nuovi account.


Creiamo ora il nostro login in PHP, che conterrà, lontano dagli occhi del client, le informazioni di autenticazione:


PHP:
<?// <editor-fold defaultstate="collapsed" desc="auth-data">$host = "localhost";$user = "root"; //username del vostro DBMS$pass = "root"; //password del vostro DBMS$nomeDB = "dbname"; //il nome del vostro DB// </editor-fold>
mysql_connect( $host, $user, $pass ) or die( "Impossibile effettuare la connessione!" );mysql_select_db( $nomeDB ) or die( "Impossibile selezionare il DB scelto" );

function anti_injection_login( $sql, $isPass ){$sql = preg_replace( "/(from|select|insert|delete|where|drop table|show tables|,|'|#|\*|--|\\\\)/i", "", $sql );
$sql = trim($sql);$sql = strip_tags($sql);
if( $isPass ){$sql = addslashes($sql);$sql = md5(trim($sql));return $sql;}else{$sql = addslashes($sql);return $sql;}
}

$clientHash = anti_injection_login( $_POST["hash"], false );
$accountName = anti_injection_login( $_POST["nick"], false ); $password = anti_injection_login( $_POST["pass"], true);
$serverHash = "codiceHash"; //qui si può generare un hash calcolato su username e password, ma questo lo farete voi ;)
if( !$accountName || !$password )     echo "Devi inserire l'username o la password.";else {
if( $clientHash != $serverHash )    echo "Errore nell'invio del hash.";else {        $querySQL = "SELECT * FROM Account WHERE AccountName = '" . $accountName . "'";        $result = mysqli_query( $querySQL ) or die( "Errore!" );        $numRows = mysql_num_rows( $result );
        if( $numRows > 0 ) {            $data = mysqli_fetch_array( $result );
            if( !strcmp( $password, $data["Password"] ) )                echo "Login effettuato con successo!";            else                 echo "Password errata.";         } else            echo "Informazioni errate.";
    }}
mysql_close();?>


Salviamo la pagina creata (login.php o come preferite). Essa va caricata sul vostro spazio web in modo da poter accedere al server MySQL presente sulla macchina. Scegliete il percorso che più vi aggrada, ma ricordate di indicarlo correttamente nello script.


Ora, nel vostro progetto Unity, create un nuovo script (l'esempio lo porto in C#, ma potete benissimo adattarlo per il Javascript):


PHP:
using UnityEngine;using System.Collections;public class GameLogin : MonoBehaviour {private string username = String.Empty;private string password = String.Empty;public string response = String.Empty; 
public string url = "http://mhlab.altervista.org/boxwar/login.php"; //cambiate questa string inserendo l'indirizzo del vostro login.php
public string hash = "codicehash"; //qui si può calcolare un hash basato su username e password, da mandare al server per verificare la correttezza dei dati inviati, ma questo lo farete voi ;)
function OnGUI() {    GUI.Label( Rect (10, 10, 80, 20), "Username:" );    GUI.Label( Rect (10, 30, 80, 20), "Password:" );
    username = GUI.TextField( Rect (90, 10, 100, 20), username );    password = GUI.PasswordField ( Rect (90, 30, 100, 20), password, '*' );
    if ( GUI.Button ( Rect (10, 60, 100, 20) , "Login" ) )        Login();
    GUI.TextArea( Rect (10, 150, 500, 500), response );}
function Login() {
    WWWForm form = new WWWForm();
    form.AddField( "hash", hash );    form.AddField( "username", username );    form.AddField( "password", password );
    WWW w = WWW(url, form);    yield w;    if (w.error != null)        print(w.error);    else {        response = w.data;        w.Dispose();    }
    username = String.Empty;
    password = String.Empty;}}


Basta inserire questo script in un GameObject. Ci sono molte migliorie e features addizionali da aggiungere (che ho omesso, visto che le userò per il mio progetto), ma penso che possa essere d'aiuto e fornire una base di partenza per chi vuole sviluppare qualcosa di suo.


Approfondimento:
E' buona norma eliminare dalla memoria le informazioni sensibili, se non più necessarie. Questo rende più difficile l'intercettazione dei dati per un utente malintenzionato. Logicamente, basta sostituire il contenuto delle aree di memoria interessate, sovrascrivendo il contenuto delle variabili. Posso segnalarvi il metodo di zero-fill contenuto in Kernel32: ZeroMemory. Tale metodo sovrascrive tutti i bit nell'area di memoria del workspace assegnato al processo, sostituendoli con degli "0".


Approfondimento:
E' buona norma non trasmettere i dati in chiaro. Per questo scopo, dovete utilizzare qualche sistema che vi permetta di non mostrare all'utente (direttamente o indirettamente) qualcosa che può essere utilizzato in modo malevolo. Esistono diversi algoritmi che "camuffano" l'informazione, privandola di significato per chi non conosce la chiave di lettura di essa.
Tali metodi sono detti metodi di criptazione e ne esistono molteplici (AES, DES, Tea, Blowfish, ecc).
Potete, inoltre, utilizzare algoritmi di hashing, che fanno perdere significato all'informazione rendendola non interpretabile da altri. Per definizione, però, l'hashing è irreversibile e non è possibile ricavare di nuovo l'informazione originale (salvo alcuni casi, purtroppo).










Ribadisco il concetto che quanto mostrato precedentemente fornisce una BASE di sviluppo di una funzionalità d'accesso valida. Tale metodo, come strutturato in questo caso, non fornisce sicurezza alcuna dei dati, i quali sono trasmessi in chiaro. Ergo, per la sicurezza delle informazioni, è necessaria l'aggiunta di ulteriori features e accorgimenti atti a rendere difficile l'intercettazione di dati sensibili. Non mostrerò, in questa guida, altre metodologie per la salvaguardia dei dati sensibili e per la loro trasmissione (chissà, forse in futuro).


Non mi assumo responsabilità alcuna di eventuali falle nella sicurezza, dovute ad un uso inappropriato del sistema mostrato sopra (in quanto non completo e privo di accorgimenti di sicurezza).



Saluti!
 
Buona guida, un consiglio che ti do è mettere VARCHAR(32) alla password invece che 50, l'hash md5 avrà sempre 32 caratteri, così risparmi spazio, il tuo MySQL te ne sarà grato.
 
  • Mi piace
Reazioni: TIH
Stato
Discussione chiusa ad ulteriori risposte.