65

状況:

ユーザーが入力した内容をエコーせずstdinに、コンソールからパスワード エントリを取得したい。Goの機能に匹敵するものはありますか?getpasswd

私が試したこと:

を使用してみsyscall.Readましたが、入力内容が反映されます。

4

10 に答える 10

117

以下は、それを実現するための最良の方法の 1 つです。最初にtermパッケージを取得するgo get golang.org/x/term

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "syscall"

    "golang.org/x/term"
)

func main() {
    username, password, _ := credentials()
    fmt.Printf("Username: %s, Password: %s\n", username, password)
}

func credentials() (string, string, error) {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Enter Username: ")
    username, err := reader.ReadString('\n')
    if err != nil {
        return "", "", err
    }

    fmt.Print("Enter Password: ")
    bytePassword, err := term.ReadPassword(int(syscall.Stdin))
    if err != nil {
        return "", "", err
    }

    password := string(bytePassword)
    return strings.TrimSpace(username), strings.TrimSpace(password), nil
}

http://play.golang.org/p/l-9IP1mrhA

于 2015-09-24T18:31:08.687 に答える
30

#go-nuts メーリングリストでメールを見ました。非常に単純な go パッケージを作成して使用する人がいます。ここで見つけることができます: https://github.com/howeyc/gopass

それはそのようなものです:

package main

import "fmt"
import "github.com/howeyc/gopass"

func main() {
    fmt.Printf("Password: ")
    pass := gopass.GetPasswd()
    // Do something with pass
}
于 2012-11-15T08:07:32.563 に答える
7

これを行うには、execを実行stty -echoしてエコーをオフstty echoにし、パスワードを読み取ってからオンに戻します。

于 2010-01-26T03:37:20.737 に答える
5

これは、Go1.6.2 を使用して開発した便利なソリューションです。

次の標準パッケージのみを使用します: bufio、、、および。より具体的には、およびを使用して stty を呼び出し、ターミナル エコーを無効/有効にします。fmtosstringssyscallsyscall.ForkExec()syscall.Wait4()

Linux と BSD (Mac) でテストしました。Windows では動作しません。

// getPassword - Prompt for password. Use stty to disable echoing.
import ( "bufio"; "fmt"; "os"; "strings"; "syscall" )
func getPassword(prompt string) string {
    fmt.Print(prompt)

    // Common settings and variables for both stty calls.
    attrs := syscall.ProcAttr{
        Dir:   "",
        Env:   []string{},
        Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
        Sys:   nil}
    var ws syscall.WaitStatus

    // Disable echoing.
    pid, err := syscall.ForkExec(
        "/bin/stty",
        []string{"stty", "-echo"},
        &attrs)
    if err != nil {
        panic(err)
    }

    // Wait for the stty process to complete.
    _, err = syscall.Wait4(pid, &ws, 0, nil)
    if err != nil {
        panic(err)
    }

    // Echo is disabled, now grab the data.
    reader := bufio.NewReader(os.Stdin)
    text, err := reader.ReadString('\n')
    if err != nil {
        panic(err)
    }

    // Re-enable echo.
    pid, err = syscall.ForkExec(
        "/bin/stty",
        []string{"stty", "echo"},
        &attrs)
    if err != nil {
        panic(err)
    }

    // Wait for the stty process to complete.
    _, err = syscall.Wait4(pid, &ws, 0, nil)
    if err != nil {
        panic(err)
    }

    return strings.TrimSpace(text)
}
于 2016-05-07T17:23:58.927 に答える
2

Go ForkExec() 関数を使用して stty を起動する必要があります。

package main

import (
    os      "os"
    bufio   "bufio"
    fmt     "fmt"
    str     "strings"
)

func main() {
    fmt.Println();
    if passwd, err := Getpasswd("Enter password: "); err == nil {
        fmt.Printf("\n\nPassword: '%s'\n",passwd)
    }
}

func Getpasswd(prompt string) (passwd string, err os.Error) {
    fmt.Print(prompt);
    const stty_arg0  = "/bin/stty";
    stty_argv_e_off := []string{"stty","-echo"};
    stty_argv_e_on  := []string{"stty","echo"};
    const exec_cwdir = "";
    fd := []*os.File{os.Stdin,os.Stdout,os.Stderr};
    pid, err := os.ForkExec(stty_arg0,stty_argv_e_off,nil,exec_cwdir,fd);
    if err != nil {
        return passwd, os.NewError(fmt.Sprintf("Failed turning off console echo for password entry:\n\t%s",err))
    }
    rd := bufio.NewReader(os.Stdin);
    os.Wait(pid,0);
    line, err := rd.ReadString('\n');
    if err == nil {
        passwd = str.TrimSpace(line)
    } else {
        err = os.NewError(fmt.Sprintf("Failed during password entry: %s",err))
    }
    pid, e := os.ForkExec(stty_arg0,stty_argv_e_on,nil,exec_cwdir,fd);
    if e == nil {
        os.Wait(pid,0)
    } else if err == nil {
        err = os.NewError(fmt.Sprintf("Failed turning on console echo post password entry:\n\t%s",e))
    }
    return passwd, err
}
于 2010-01-26T08:16:46.563 に答える
1

https://github.com/peterh/linerパッケージPasswordPromptの機能を使用することもできます。

于 2016-05-06T23:38:59.813 に答える
-4

os.File オブジェクト (または os.Stdin 変数) から Read メソッドを使用して、必要な動作を取得できます。次のサンプル プログラムは、(リターン キーを押して終了する) テキスト行を読み取りますが、fmt.Printf 呼び出しまでエコーしません。

package main

import "fmt"
import "os"

func main() {
  var input []byte = make( []byte, 100 );
  os.Stdin.Read( input );
  fmt.Printf( "%s", input );
}

より高度な動作が必要な場合は、おそらく Go C ラッパー ユーティリティを使用して、低レベルの API 呼び出し用のラッパーを作成する必要があります。

于 2010-01-26T05:01:04.610 に答える