Riprendo a scrivere qualcosa di (spero) utile su MySQL e tratto un argomento strano: gli utenti. In realtà MySQL ha sempre avuto un sistema molto potente per la gestione dei permessi, che quasi tutti hanno sempre ignorato creando o utilizzando (in hosting) un utente che ha tutti i permessi possibili almeno sui suoi database. Ma vale la pena di saperne di più.
In realtà bisogna distinguere tra:
- Autenticazione - il login, l’accesso al sistema nudo e crudo
- Permessi - ciò che un utente può o non può fare dopo il login
Per ora parleremo solo di autenticazione, accennando appena ai permessi. Peraltro ciò di cui parleremo prima o poi cambierà, in quanto gli sviluppatori hanno in previsione di creare un sistema di plugin anche per l’autenticazione. In questo modo sarà possibile, oltre ad autenticarsi come già si fa oggi, affidare il riconoscimento degli utenti ad altri software, come ad esempio Kerberos. Per ulteriori info, vedi questo worklog.
Creare un utente
Per creare un nuovo utente in genere si usa l’istruzione CREATE USER, la cui sintassi è:
CREATE USER utente [IDENTIFIED BY [PASSWORD] ‘password’] [, user ...]
utente è il nome dell’utente che stiamo creando.
IDENTIFIED BY [PASSWORD] indica la password da abbinargli. La ragione per cui la clausola non è obbligatoria è che un utente MySQL può anche non avere una password (sconsigliatissimo).
Con una sola istruzione è possibile creare più utenti.
Esempi:
CREATE USER pippo
CREATE USER pippo@topolinia.net
CREATE USER pippo IDENTIFIED BY ‘yukgaspgulp’
Questo può essere anche indicato con la formula ‘nome_utente’@'nome_host’; così facendo, l’utente che stiamo creando sarà utilizzanto solo quando il nome_utente viene usato da nome_host. Si può anche utilizzare il carattere ‘%’, che funzionerà esattamente come funziona in LIKE. Per esempio ‘utente1′@’%.php.net’ permette a utente1 di connettersi da qualsiasi host che faccia parte della sottorete di php.net.
Per create un utente abbiamo bisogno del permesso ‘CREATE USER’.
INFORMATION_SCHEMA
Forse il modo più amichevole per vedere gli utenti esistenti è utilizzare la tabella `USER_PRIVILEGES` del database virtuale `INFORMATION_SCHEMA`. Naturalmente si tratta di una tabella a sola lettura, utilizzabile solo per conoscere gli utenti e non per modificarli. Le due colonne sono:
- GRANTEE - contiene il nome utente nella formula ‘nome_utente’@'nome_host’, anche quando il nome dell’host non è stato specificato in fase di creazione;
- TABLE_CATALOG - inutilizzata (è prevista dall’SQL standard ma in MySQL è sempre null perchè allo stato attuale non esistono i cataloghi; vedi questo worklog)
- PRIVILEGE_TYPE - un tipo di privilegio assegnato all’utente: per ogni privilegio assegnato c’è una riga;
- IS_GRANTABLE - vale ‘YES’ o ‘NO’ e indica se l’utente può assegnare o revocare questo permesso ad altri utenti con le istruzioni CREATE USER, GRANT e REVOKE.
Si, ma dove sono gli utenti?
Le tabelle presenti nell’INFORMATION_SCHEMA sono appunto virtuali e di sola lettura. Ma dove sono registrati fisicamente gli utenti e i loro permessi?
Nel database di sistema ‘mysql’. Bisogna fare molta attenzione nel modificarlo direttamente con le istruzioni INSERT, UPDATE e DELETE, perchè creare incongruenze proprio in questo database può pregiudicare il corretto funzionamento di MySQL. Vi ho terrorizzati? No? Peggio per voi, vorrà dire che farete un pasticcio e dovrete reinstallare tutto. Così imparate a non darmi retta. Ed è inutile che mi mandiate le mail per dirmi “avevi ragione, dovevo stare più attento”, perchè ormai il patatrak è fatto. Vabbè, andiamo avanti :)
L’unica tabella che esamineremo in questo articolo è user. Le sue colonne sono:
- Host - il nome dell’host associato all’utente (’%’ significa ‘qualsiasi host’);
- User - il nome utente;
- Password - la sua password criptata con un algoritmo a una via (si può confrontarla con un’altra password criptandola allo stesso modo e vedere se corrisponde, ma non si può decriptarla);
- ssl_type - il tipo di connessione SSL usata dall’utente (connessione criptata), se usata;
- ssl-cipher - la chiave pubblica, se usata;
- x509_issuer - ente emettitore del certificato SSL, se c’è;
- x509_subject - soggetto del certificato SSL, se c’è;
- max_questions - massimo di domande (SELECT, SHOW, DESCRIBE, HELP) eseguibili in un’ora, 0=nessun limite;
- max_updates - numero di scritture sulle tabelle eseguibili in un’ora, 0=nessun limite;
- max_connections - ?
- max_user_connections - numero di connessioni eseguibili in un’ora, 0=nessun limite;
I privilegi
Per non occupare troppo spazio non ho elencato le colonne relative ai privilegi. Di questi non ci occupiamo più di tanto in questo articolo. Per ora, basti dire che per ogni tipo di privilegio esiste una colonna denominata nomeprivilegio_priv. Per esempio: Inser_priv, Update_priv, Delete_priv. Questo colonne possono avere come valore ‘Y’ o ‘N’.
Le risorse
Le ultime colonne servono a dare un limite alle risorse utilizzabili da ogni singolo utente. Se non avete queste colonne significa che state usando una versione piuttosto vecchia di MySQL, passando ad una versione recente potrete aggiungerle con lo script mysql_upgrade. I limiti sono indicati su base oraria, il valore predefinito è 0 (nessun limite). Oltre che agendo direttamente su questa tabella, possono essere impostati con le istruzioni GRANT e REVOKE, di cui non ci occupiamo qui. Il contatore delle risorse utilizzate finora può essere resettato con il comando SQL FLUSH PRIVILEGES o chiamando mysqladmin reload da riga di comando. Entrambi, però, non riguardano il numero massimo di connessioni.
Altre tabelle
- host - permessi assegnati a un host su un certo database o su tutti;
- tables_priv - permessi assegnati su una tabella specifica;
- columns_priv - permessi su una colonna specifica;
- prov_priv - permessi su una procedura.
Eliminare un utente
Eliminare un utente è molto semplice:
DROP USER utente [, utente ...]
utente è naturalmente il nome dell’utente (degli utenti) che intendiamo eliminare. Il comando non elimina automaticamente i permessi associati all’utente, lasciando quindi delle voci orfane nella tabella relativa.
Per compiere questa operazione dobbiamo disporre del permesso ‘CREATE USER’ o del permesso ‘DELETE’ sul database ‘mysql’.
Cambiare un nome utente o una password
Abbiamo a disposizione due istruzioni SQL che ci permettono di cambiare il nome utente o una password senza agire sul database MySQL.
RENAME USER è stata aggiunta in MySQL 5.0.2 e la sua sintassi è:
RENAME USER nome_vecchio TO nome_nuovo [, ...]
Questa istruzione si limita a modificare il nome utente nella tabella user, ma tutti i privilegi resteranno assegnati al vecchio nome utente (che potrebbe essere ricreato).
Per cambiare una password:
SET PASSWORD [FOR 'utente'] = ‘password’
Se FOR ‘utente’ non è specificato, verrà cambiata la propria password.
utente è il nome dell’utente al quale stiamo cambiando la password.
‘password’ è la nuova password. Può essere già criptata (ma bisogna utilizzare lo stesso algoritmo della funzione PASSWORD()!), o si può usare una delle due funzioni PASSWORD() (più recente) o OLD_PASSWORD() (non sicura, ma compatibile con le vecchie versioni di MySQL). Esempio:
SET PASSWORD FOR pippo = PASSWORD(’londonburns999′)
Drizzle
Il sistema di permessi di MySQL dovrebbe essere stato completamente eliminato da Drizzle, mentre è probabile che l’autenticazione e la gestione utenti funzionino più o meno allo stesso modo. Ne sapremo di più dopo la prima release.