在Haskell命令行应用程序中提示输入密码

Hei*_*mus 26 passwords terminal command-line haskell

以下Haskell程序在终端中提示用户输入密码,如果输入正确的密码则继续:

main = do
    putStrLn "Password:"
    password <- getLine

    case hash password `member` database of
        False -> putStrLn "Unauthorized use!"
        True  -> do
                 ...
Run Code Online (Sandbox Code Playgroud)

不幸的是,密码会在用户输入时显示在屏幕上,我想避免使用.

如何在不显示屏幕的情况下读取用户输入的一系列字符?getLine为此目的的等价物是什么?

我在MacOS X上,但我希望这也适用于Windows和Linux.

Yur*_*ras 38

做这个:

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
Run Code Online (Sandbox Code Playgroud)


Dan*_*kov 15

有一个getPasswordSystem.Console.Haskeline.可能这对你的案子来说太过分了,但有人可能觉得它很有用.

一个例子:

> runInputT defaultSettings $ do {p <- getPassword (Just '*') "pass:"; outputStrLn $ fromJust p}
pass:***
asd
Run Code Online (Sandbox Code Playgroud)

  • 知道为什么所有的 Haskeline 函数都返回一个 `Maybe String` 而不是 `String` 吗?没有关于它的文档,在我看来它应该总是返回 `String`,就像标准的 `getLine`。 (2认同)

ken*_*ytm 9

有可能在与终端禁用呼应System.Posix.Terminal模块.但是,这需要POSIX支持,因此可能无法在Windows上运行(我没有检查).

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
Run Code Online (Sandbox Code Playgroud)

请注意,stdin是行缓冲的,因此如果使用putStr "Password:"而不是putStrLn,则需要先刷新缓冲区,否则也会禁止提示.


小智 6

withEcho可以写一点点噪音:

withEcho :: Bool -> IO a -> IO a
withEcho echo action =
    bracket (hGetEcho stdin)
            (hSetEcho stdin)
            (const $ hSetEcho stdin echo >> action)
Run Code Online (Sandbox Code Playgroud)