Scopo | Chiede all'utente un valore, in genere una password, senza emettere sullo schermo i cartteri digitati nella console |
Versione Python | 1.5.2 e superiore |
A partire dal 1 gennaio 2021 le versioni 2.x di Python non sono piu' supportate. Ti invito a consultare la corrispondente versione 3.x dell'articolo per il modulo getpass
Molti programmi che interagiscono con l'utente attraverso un terminale devono richiedere una password senza mostrare quello l'utente sta digitando. Il modulo getpass fornisce un modo portabile per gestire in sicurezza queste richieste
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
import getpass
p = getpass.getpass()
print 'Hai digitato:', p
Il
prompt
predefinito, se nulla è stato specificato dal chiamante, è
"Password:"
.
$ python getpass_defaults.py Password: Hai digitato: segreta
Il prompt predefinto può essere modificato con qualsiasi valore il proprio programma necessiti.
import getpass
p = getpass.getpass(prompt="Qual'è il tuo colore preferito? ")
if p.lower() == 'blu':
print 'Corretto, puoi proseguire.'
else:
print 'Auuuuugh!'
Non si consiglia uno schema di autenticazione così debole, ma si vuole solo illustrare il punto.
$ python getpass_prompt.py Qual'è il tuo colore preferito? Corretto, puoi proseguire. $ python getpass_prompt.py Qual'è il tuo colore preferito? Auuuuugh!
Nella modalità predefinita
getpass()
utilizza
stdout
per stampare la stringa
prompt
. Per un programma che debba produrre un output utilizzabile su sys.stdout, spesso è meglio indirizzare il
prompt
verso una altro flusso tipo sys.stderr.
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 il prompt per la password. Il valore digitato dall'utente non viene comunque ripetuto sullo schermo.
$ python getpass_stream.py > /dev/null Password:
Su Unix,
getpass()
richiede un
tty
(comando Unix che restituisce il nome del terminale corrente - n.d.t) 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 valorei non saranno letti da un flusso non di terminale rediretto verso lo standard input.
$ echo "sekret" | python getpass_defaults.py Traceback (most recent call last): File "getpass_defaults.py", line 34, in p = getpass.getpass() File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/getpass.py", line 32, in unix_getpass old = termios.tcgetattr(fd) # a copy to save termios.error: (25, 'Inappropriate ioctl for device')
Spetta al chiamante rilevare quando il flusso in input non è un tty ed utilizzare un metodo alternativo per la lettura in quel caso
import getpass
import sys
if sys.stdin.isatty():
p = getpass.getpass('Si usa getpass: ')
else:
print 'Si usa readline'
p = sys.stdin.readline().rstrip()
print 'Letto: ', p
Con un tty
$ python getpass_noterminal.py Si usa getpass: Letto: segreta
Senza un tty
$ echo "segreta" | python getpass_noterminal.py Si usa readline: Letto: segreta