getpass - Prompt di Password Sicuro
Scopo: Chiede all'utente un valore, in genere una password, senza emettere sullo schermo i caratteri digitati nella console
Molti programmi che interagiscono con l'utente attraverso un terminale devono richiedere una password senza mostrare nello schermo quello che l'utente sta digitando. Il modulo getpass fornisce un modo portabile per gestire in sicurezza queste richieste.
Esempio
La funzione getpass()
stampa un prompt che legge l'input digitato dall'utente, fino a che egli non preme Invio. Quanto digitato viene poi passato come stringa al chiamante.
# getpass_defaults.py
import getpass
try:
p = getpass.getpass()
except Exception as err:
print('ERRORE:', err)
else:
print('Hai digitato: {}'.format(p))
Il prompt predefinito, se nulla è stato specificato dal chiamante, è "Password:"
.
$ python3 getpass_defaults.py Password: Hai digitato: segreto
Il prompt predefinto può essere modificato con qualsiasi valore si necessiti.
# getpass_prompt.py
import getpass
p = getpass.getpass(prompt='Quale è il tuo colore preferito? ')
if p.lower() == 'blu':
print('Bene. Puoi andare.')
else:
print('Auuuuugh!')
Alcuni programmi richiedono una frase d'accesso invece che una semplice password, per fornire migliore sicurezza.
$ python3 getpass_prompt.py Quale è il tuo colore preferito? Bene. Puoi andare.
$ python3 getpass_prompt.py Quale è il tuo colore preferito? Auuuuugh!
Nella modalità predefinita getpass()
utilizza sys.stdout
per stampare la stringa di richiesta. Per un programma che debba produrre un output significativo su sys.stdout
, spesso è meglio indirizzare il prompt verso una altro flusso tipo sys.stderr
.
# getpass_stream.py
import getpass
import sys
p = getpass.getpass(stream=sys.stderr)
print('Hai digitato:', p)
In questo modo l'output standard può essere rediretto (ad un pipe oppure ad un file) senza vedere la richiesta password. Il valore digitato dall'utente non viene comunque ripetuto sullo schermo.
$ python3 getpass_stream.py > /dev/null Password:
Utilizzare getpass Senza un Terminale
Su Unix, getpass()
richiede un terminale che possa controllare tramite termios
(una struttura dati utilizzata da tutte le chiamate di libreria del terminale - n.d.t.) in modo che la ripetizione dei caratteri sullo schermo possa essere disabilitata. Il che significa che i valori non saranno letti da un flusso non di terminale rediretto verso lo standard input; invece getpass
cerca di ottenere il terminale per un processo e non viene sollevato alcun errore se è possibile accedervi.
$ echo "segreto" | python getpass_defaults.py Password: Hai digitato: segreto
Spetta al chiamante rilevare quando il flusso in input non è un terminale ed utilizzare un metodo alternativo per la lettura in quel caso.
# getpass_noterminal.py
import getpass
import sys
if sys.stdin.isatty():
p = getpass.getpass('Si sta usando getpass: ')
else:
print('Si sta usando readline')
p = sys.stdin.readline().rstrip()
print('Letto: ', p)
Con un terminale:
$ python3 getpass_noterminal.py Si sta usando getpass: Letto: segreto
Senza un terminale:
$ echo "segreto" | python getpass_noterminal.py Si sta usando readline Letto: segreto