ver type password mdn formulario current contraseƱa atributos passwords stdin go getpasswd

passwords - type - Funcionalidad getpasswd en Go?



placeholder contraseƱa (8)

Quisiera poder ingresar la contraseña desde la consola stdin, pero, por supuesto, sin repetir lo que escribe el usuario.

¿Hay algo comparable a la funcionalidad getpasswd en Go? (Idioma de Go de Google)

Intenté usar syscall.Read, pero se hace eco de lo que se escribe.


Acabo de ver un correo en # go-nuts maillist. Hay alguien que escribió un paquete bastante simple para ser utilizado. Puede encontrarlo aquí: https://github.com/howeyc/gopass

Es algo así:

package main import "fmt" import "github.com/howeyc/gopass" func main() { fmt.Printf("Password: ") pass := gopass.GetPasswd() // Do something with pass }


Aquí hay una solución que desarrollé usando Go1.6.2 que podría serle útil.

Solo utiliza los siguientes paquetes estándar: bufio, fmt, reader, strings y syscall. Más específicamente, usa syscall.ForkExec() y syscall.Wait4() para invocar a stty para deshabilitar / habilitar el eco del terminal.

Lo he probado en Linux y BSD (Mac). No funcionará en Windows.

// getPassword - Prompt for password. Use stty to disable echoing. 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) }


Aquí hay una versión específica para Linux:

func terminalEcho(show bool) { // Enable or disable echoing terminal input. This is useful specifically for // when users enter passwords. // calling terminalEcho(true) turns on echoing (normal mode) // calling terminalEcho(false) hides terminal input. var termios = &syscall.Termios{} var fd = os.Stdout.Fd() if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, syscall.TCGETS, uintptr(unsafe.Pointer(termios))); err != 0 { return } if show { termios.Lflag |= syscall.ECHO } else { termios.Lflag &^= syscall.ECHO } if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(termios))); err != 0 { return } }

Entonces para usarlo:

fmt.Print("password: ") terminalEcho(false) var pw string fmt.Scanln(&pw) terminalEcho(true) fmt.Println("")

Es el syscall de TCGETS que es específico de Linux. Hay diferentes valores de syscall para OSX y Windows.


La siguiente es una de las mejores maneras de hacerlo. Primero obtenga el paquete de terminal por go get golang.org/x/crypto/ssh

package main import ( "bufio" "fmt" "os" "strings" "syscall" "golang.org/x/crypto/ssh/terminal" ) func main() { username, password := credentials() fmt.Printf("Username: %s, Password: %s/n", username, password) } func credentials() (string, string) { reader := bufio.NewReader(os.Stdin) fmt.Print("Enter Username: ") username, _ := reader.ReadString(''/n'') fmt.Print("Enter Password: ") bytePassword, err := terminal.ReadPassword(int(syscall.Stdin)) if err == nil { fmt.Println("/nPassword typed: " + string(bytePassword)) } password := string(bytePassword) return strings.TrimSpace(username), strings.TrimSpace(password) }

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


Lanzamiento requerido a través de la función Go ForkExec ():

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 }


Puede obtener el comportamiento que desea con el método Read desde el objeto os.File (o la variable os.Stdin). El siguiente programa de ejemplo leerá una línea de texto (terminada con presionar la tecla de retorno) pero no se repetirá hasta la llamada fmt.Printf.

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

Si desea un comportamiento más avanzado, es probable que tenga que utilizar las herramientas Go C-wrapper y crear algunos contenedores para llamadas api de bajo nivel.



puede hacer esto al ejecutar stty -echo para desactivar el eco y luego stty echo después de leer la contraseña para volver a activarlo