C命令行密码输入

时间:2009-11-23 22:33:06

标签: c input passwords

我想允许用户使用命令行界面输入密码。但我不想在屏幕上显示此密码(或显示“****”)。

如何在C中执行此操作? 感谢。

更新

我只在Linux上工作。所以我实际上并不关心Win或其他系统。我试过卢卡斯的解决方案,它工作得很好。但是,我还有另一个问题:

  1. 如果这是一个单一的过程&单线程应用程序,更改termios的设置会影响不同的终端吗?

  2. 1个进程怎么样 - 多线程,多进程 - 多线程?

  3. 非常感谢。

7 个答案:

答案 0 :(得分:16)

如果您的系统提供,getpass是一个选项:

#include <unistd.h>
/* ... */
char *password = getpass("Password: ");

在键入字符时不会显示任何内容。

答案 1 :(得分:9)

如果您使用的是UNIX环境,则可以关闭命令行的ECHO。

#include <stdio.h>
#include <termios.h>
#include <unistd.h>   

#define SIZE 100

void getPassword(char password[])
{
    static struct termios oldt, newt;
    int i = 0;
    int c;

    /*saving the old settings of STDIN_FILENO and copy settings for resetting*/
    tcgetattr( STDIN_FILENO, &oldt);
    newt = oldt;

    /*setting the approriate bit in the termios struct*/
    newt.c_lflag &= ~(ECHO);          

    /*setting the new bits*/
    tcsetattr( STDIN_FILENO, TCSANOW, &newt);

    /*reading the password from the console*/
    while ((c = getchar())!= '\n' && c != EOF && i < SIZE){
        password[i++] = c;
    }
    password[i] = '\0';

    /*resetting our old STDIN_FILENO*/ 
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);

}


int main(void)
{
    char password[SIZE];
    printf("please enter password\n");
    getPassword(password);

    printf("Do something with the password <<%s>>\n", password);
    return 0;
}

答案 2 :(得分:4)

函数getpass现在是obsolete。使用termios

#include <termios.h>
#include <stdio.h>

void get_password(char *password)
{
    static struct termios old_terminal;
    static struct termios new_terminal;

    //get settings of the actual terminal
    tcgetattr(STDIN_FILENO, &old_terminal);

    // do not echo the characters
    new_terminal = old_terminal;
    new_terminal.c_lflag &= ~(ECHO);

    // set this as the new terminal options
    tcsetattr(STDIN_FILENO, TCSANOW, &new_terminal);

    // get the password
    // the user can add chars and delete if he puts it wrong
    // the input process is done when he hits the enter
    // the \n is stored, we replace it with \0
    if (fgets(password, BUFSIZ, stdin) == NULL)
        password[0] = '\0';
    else
        password[strlen(password)-1] = '\0';

    // go back to the old settings
    tcsetattr(STDIN_FILENO, TCSANOW, &old_terminal);
}

int main(void)
{
    char password[BUFSIZ];

    puts("Insert password:");
    get_password(password);
    puts(password);
}

答案 3 :(得分:2)

对于C /命令行/ linux,请参阅:

man getch
man noecho

请参阅getch中有关noecho的评论。我自己从未尝试过这个。

如果使用read -s,则在bash中,它不会在屏幕上回显:

> read -s x
<type something><enter>
> echo $x
<whatever you typed>

答案 4 :(得分:1)

要以便携方式执行此操作,您需要使用标准化或事实上的标准库。

请参阅man 3 termiosman 3 ncurses

这是一个适用于Linux和其他Unix系统的程序......

#include <stdio.h>

int main(void) {
  int f = open("/dev/tty", 0);
  char s[100];

  system("stty -echo > /dev/tty");
  f >= 0 && read(f, s, sizeof s) > 0 &&  printf("password was %s", s);
  system("stty echo > /dev/tty");
  return 0;
}

可以进行一些改进。使用termios可能会更好,它可以避免fork()和system()可能出现的安全问题。使用标准I / O来读取密码可能会更好。 (正如所写的那样,必须删除键入的换行符。)Linux中有一个getpass()函数,但是它被标记为“过时了。不要使用它。”。处理SIGTSTP可能是个好主意。

总的来说,我可能会寻找一个处理所有这些小问题的现有解决方案......

答案 5 :(得分:1)

如果您有权访问curses库,则可以使用noecho。如果您使用的是Microsoft的C编译器,则可以使用_getch。但是afaik,这两个都把你绑在控制台上。如果你需要读取stdin而不管它是来自控制台还是文件或管道命令,你需要告诉操作系统它应该如何handle the console

答案 6 :(得分:0)

     #include<conio.h>
     #include<iostream>
     using namespace std;
     int main(){
     char *pass = new char[20];
     cout<<"Password :";
     int i=0;   
     while( ( pass[i]=getch() ) != '\n' && pass[i] != '\r' && i<19 )
     {putchar('*'); i++;}
     pass[i]='\0';
     cout<<endl;
     if(strcmp("123456789",pass)==0 ) // do stuff
     return 0;}