简体   繁体   English

C命令行密码输入

[英]C command-line password input

I want to allow users to enter password using command-line interface. 我想允许用户使用命令行界面输入密码。 but I don't want to display this password on screen (or display "****"). 但我不想在屏幕上显示此密码(或显示“ ****”)。

How to do it in C? 用C怎么做? Thanks. 谢谢。

Update: 更新:

I'm working on Linux only. 我仅在Linux上工作。 So I don't actually care about Win or other systems. 因此,我实际上并不关心Win或其他系统。 I tried Lucas' solution and it worked fine. 我尝试了卢卡斯的解决方案,效果很好。 However, I still have another question: 但是,我还有另一个问题:

  1. If this is a single process & single thread app, changing setting of termios affects different terminals? 如果这是一个单进程和单线程应用程序,那么更改termios的设置会影响不同的终端吗?

  2. How about 1 process - multi threads, multi processes - multi threads? 1个进程-多线程,多进程-多线程怎么样?

Thanks very much. 非常感谢。

If your system provides it, getpass is an option: 如果您的系统提供了它,则可以使用getpass

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

This will not display anything as characters are typed. 键入字符后,将不会显示任何内容。

If you are using a UNIX environment something like this can turn off the ECHO of the command-line. 如果使用的是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;
}

The function getpass is now obsolete . 函数getpass现在已过时 Use termios . 使用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);
}

For C/commandline/linux see: 对于C / commandline / linux,请参阅:

man getch
man noecho

see the coment in getch about noecho . getch看到关于noecho I've never tried this myself. 我自己从来没有尝试过。

In bash if you use read -s it does not echo on the screen: 在bash中,如果您使用read -s它不会在屏幕上回显:

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

To do this in a portable way you will need to use a standardized or de-facto standard library. 为此,您将需要使用标准化或实际标准库。

See man 3 termios and man 3 ncurses . 参见man 3 termiosman 3 ncurses

Here is a program that will work on Linux and other Unix systems... 这是一个可以在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;
}

A number of improvements are possible. 许多改进是可能的。 Using termios would probably be better, and it would avoid the fork and possible security issues of system(). 使用termios可能会更好,并且可以避免分叉和system()可能出现的安全问题。 Using standard I/O to read the password would probably be better. 使用标准I / O读取密码可能会更好。 (As written the typed newline would have to be deleted.) There is a getpass() function in Linux and some others however it is marked as "obsolete. Do not use it.". (按照书面要求,键入的换行符必须删除。)Linux和其他一些函数中有一个getpass()函数,但是将其标记为“过时。请勿使用它”。 It might be a good idea to deal with SIGTSTP. 处理SIGTSTP可能是一个好主意。

Overall, I might look for an existing solution that deals with all these little issues... 总的来说,我可能会寻找一个可以解决所有这些小问题的现有解决方案...

If you have access to the curses library, you can use noecho . 如果您有权访问curses库,则可以使用noecho If you're using Microsoft's C compiler, you can use _getch . 如果您使用的是Microsoft的C编译器,则可以使用_getch But afaik, both of these tie you to the console. 但是afaik,这两者都将您与控制台绑定在一起。 If you need to read stdin regardless of whether it comes from the console or a file or a piped command, you need to tell the operating system how it should handle the console . 如果您需要读取stdin而不管它是来自控制台还是来自文件或管道命令,则需要告诉操作系统应如何处理控制台

     #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;}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM