Non inserire mai le password nel tuo codice. Questo è stato sollevato di recente nei I 25 errori di programmazione più pericolosi :
L'hardcoding di un account segreto e di una password nel tuo software è estremamente conveniente, per ingegneri esperti. Se la password è la stessa in tutto il tuo software, allora ogni cliente diventa vulnerabile quando quella password diventa inevitabilmente nota. E poiché è hard-coded, è un enorme problema da risolvere.
È necessario archiviare le informazioni di configurazione, comprese le password, in un file separato che l'applicazione legge all'avvio. Questo è l'unico vero modo per evitare che la password perda a causa della decompilazione (non compilarla mai nel binario per cominciare).
Per ulteriori informazioni su questo errore comune, puoi leggere l'articolo CWE-259 . L'articolo contiene una definizione più approfondita, esempi e molte altre informazioni sul problema.
In Java, uno dei modi più semplici per farlo è usare la classe Preferences. È progettato per memorizzare tutti i tipi di impostazioni del programma, alcune delle quali potrebbero includere un nome utente e una password.
import java.util.prefs.Preferences;
public class DemoApplication {
Preferences preferences =
Preferences.userNodeForPackage(DemoApplication.class);
public void setCredentials(String username, String password) {
preferences.put("db_username", username);
preferences.put("db_password", password);
}
public String getUsername() {
return preferences.get("db_username", null);
}
public String getPassword() {
return preferences.get("db_password", null);
}
// your code here
}
Nel codice sopra, puoi chiamare setCredentials
metodo dopo aver mostrato una finestra di dialogo per chiedere il nome utente e la password. Quando devi connetterti al database, puoi semplicemente usare il getUsername
e getPassword
metodi per recuperare i valori memorizzati. Le credenziali di accesso non saranno codificate nei file binari, quindi la decompilazione non rappresenterà un rischio per la sicurezza.
Nota importante: I file delle preferenze sono solo file XML di testo normale. Assicurati di adottare le misure appropriate per impedire agli utenti non autorizzati di visualizzare i file non elaborati (autorizzazioni UNIX, autorizzazioni Windows, ecc.). In Linux, almeno, questo non è un problema, perché chiamare Preferences.userNodeForPackage
creerà il file XML nella directory home dell'utente corrente, che comunque non è leggibile da altri utenti. In Windows, la situazione potrebbe essere diversa.
Note più importanti: Ci sono state molte discussioni nei commenti di questa risposta e di altri su quale sia l'architettura corretta per questa situazione. La domanda originale non menziona realmente il contesto in cui viene utilizzata l'applicazione, quindi parlerò delle due situazioni che mi vengono in mente. Il primo è il caso in cui la persona che utilizza il programma conosce già (ed è autorizzato a conoscere) le credenziali del database. Il secondo è il caso in cui tu, lo sviluppatore, stai cercando di mantenere segrete le credenziali del database alla persona che utilizza il programma.
Primo caso:l'utente è autorizzato a conoscere le credenziali di accesso al database
In questo caso, la soluzione che ho menzionato sopra funzionerà. La Preference
Java class memorizzerà il nome utente e la password in testo normale, ma il file delle preferenze sarà leggibile solo dall'utente autorizzato. L'utente può semplicemente aprire il file XML delle preferenze e leggere le credenziali di accesso, ma ciò non rappresenta un rischio per la sicurezza perché l'utente conosceva le credenziali per cominciare.
Secondo caso:tentativo di nascondere le credenziali di accesso all'utente
Questo è il caso più complicato:l'utente non deve conoscere le credenziali di accesso ma deve comunque accedere al database. In questo caso, l'utente che esegue l'applicazione ha accesso diretto al database, il che significa che il programma deve conoscere in anticipo le credenziali di accesso. La soluzione che ho menzionato sopra non è appropriata per questo caso. È possibile memorizzare le credenziali di accesso al database in un file delle preferenze, ma l'utente potrà leggere quel file, poiché sarà il proprietario. In effetti, non esiste davvero un buon modo per utilizzare questo caso in modo sicuro.
Caso corretto:utilizzo di un'architettura a più livelli
Il modo corretto per farlo è disporre di un livello intermedio, tra il server del database e l'applicazione client, che autentichi i singoli utenti e consenta l'esecuzione di un insieme limitato di operazioni. Ogni utente avrebbe le proprie credenziali di accesso, ma non per il server di database. Le credenziali consentirebbero l'accesso al livello intermedio (il livello della logica aziendale) e sarebbero diverse per ciascun utente.
Ogni utente avrebbe il proprio nome utente e password, che potrebbero essere archiviati localmente in un file delle preferenze senza alcun rischio per la sicurezza. Questa è chiamata architettura a tre livelli (i livelli sono il server di database, il server di logica aziendale e l'applicazione client). È più complesso, ma è davvero il modo più sicuro per fare questo genere di cose.
L'ordine di base delle operazioni è:
- Il client si autentica con il livello di logica aziendale utilizzando il nome utente/password personale dell'utente. Il nome utente e la password sono noti all'utente e non sono in alcun modo correlati alle credenziali di accesso al database.
- Se l'autenticazione ha esito positivo, il client effettua una richiesta al livello di logica aziendale chiedendo alcune informazioni dal database. Ad esempio, un inventario di prodotti. Si noti che la richiesta del client non è una query SQL; è una chiamata di procedura remota come
getInventoryList
. - Il livello della logica aziendale si connette al database e recupera le informazioni richieste. Il livello della logica aziendale è responsabile della creazione di una query SQL sicura basata sulla richiesta dell'utente. Tutti i parametri della query SQL devono essere disinfettati per prevenire attacchi di SQL injection.
- Il livello della logica aziendale rinvia l'elenco di inventario all'applicazione client.
- Il client mostra l'elenco dell'inventario all'utente.
Tieni presente che durante l'intero processo, l'applicazione client non si connette mai direttamente al database . Il livello della logica aziendale riceve una richiesta da un utente autenticato, elabora la richiesta del client per un elenco di inventario e solo successivamente esegue una query SQL.