Demander un mot de passe dans l'application de ligne de commande Haskell
Le programme Haskell suivant invite l'utilisateur à entrer un mot de passe dans le terminal et continue s'il a entré le bon:
main = do
putStrLn "Password:"
password <- getLine
case hash password `member` database of
False -> putStrLn "Unauthorized use!"
True -> do
...
Malheureusement, le mot de passe apparaîtra à l'écran lorsque l'utilisateur le Tapera, ce que je veux éviter.
Comment puis-je lire une séquence de caractères que les utilisateurs sans avoir à l'afficher sur l'écran? Quel est l'équivalent de
getLine
à cet effet?
Je suis sur MacOS X, mais je voudrais que cela fonctionne sur Windows et Linux, trop.
5 réponses
Essayez le suivant:
module Main
where
import System.IO
import Control.Exception
main :: IO ()
main = getPassword >>= putStrLn . ("Entered: " ++)
getPassword :: IO String
getPassword = do
putStr "Password: "
hFlush stdout
pass <- withEcho False getLine
putChar '\n'
return pass
withEcho :: Bool -> IO a -> IO a
withEcho echo action = do
old <- hGetEcho stdin
bracket_ (hSetEcho stdin echo) (hSetEcho stdin old) action
, Il est un getPassword
dans System.Console.Haskeline
. C'est probablement un excès pour votre cas, mais quelqu'un peut le trouver utile.
Un exemple:
> runInputT defaultSettings $ do {p <- getPassword (Just '*') "pass:"; outputStrLn $ fromJust p}
pass:***
asd
, Il est possible de désactiver l'écho dans le terminal avec le System.Posix.Terminal
module. Cependant, cela nécessite un support POSIX, donc peut ne pas fonctionner sur Windows (je n'ai pas vérifié).
import System.Posix.Terminal
import System.Posix.IO (stdInput)
getPassword :: IO String
getPassword = do
tc <- getTerminalAttributes stdInput
setTerminalAttributes stdInput (withoutMode tc EnableEcho) Immediately
password <- getLine
setTerminalAttributes stdInput tc Immediately
return password
main = do
putStrLn "Password:"
password <- getPassword
putStrLn "Name:"
name <- getLine
putStrLn $ "Your password is " ++ password ++ " and your name is " ++ name
Notez que le stdin est mis en mémoire tampon, donc si vous utilisez putStr "Password:"
au lieu de putStrLn
, vous devez d'abord vider le tampon, sinon l'invite sera également inhibée.
WithEcho peut être écrit avec un peu moins de noice:
withEcho :: Bool -> IO a -> IO a
withEcho echo action =
bracket (hGetEcho stdin)
(hSetEcho stdin)
(const $ hSetEcho stdin echo >> action)
Comme je l'ai commenté ci-dessus, je vous suggère d'utiliser haskeline, qui est un invite de la bibliothèque. Je l'ai utilisé heureusement pour LambdaCalculator sans se plaindre.