问题 如何在终端上以星号(*)的形式显示输入密码


我想写一个简单的 C 程序验证 password例如,如果 密码 等于 1234 然后我想要打印 欢迎 其他 再试一次。但问题如下:

我想以形式显示输入密码  *)。 例如..如果用户输入1234,它将显示为 **** 避免其他人看到输入的密码。

谁能让我知道如何使用c或c ++实现它。 平台:UNIX


12006
2017-09-23 08:59


起源

你能发布你先写的东西吗? - SSC
重复: stackoverflow.com/questions/17130979/... - Paul R
您需要指定您的平台,因为此解决方案是特定于平台的 - Cool Guy
我正在使用unix平台 - Faisal Ikwal
SO的工作原理很有趣。最初的问题得到一个downvote,这个问题已经有八个upvotes。 - user


答案:


不幸的是,解决方案是特定于平台的。

在Linux或BSD上,您可以使用 readpassphrase 功能(还有 将getpass虽然它不允许调用者提供缓冲区和缓冲区大小。的文档 GNU Lib C. (链接坏了?试试 这种选择 相反)库还提供了一个很好的指导,说明如何根据较低级别的termios原语实现这一点,您可以在其他UNIX实现上使用,而不是getpass)。

在Windows上,您可以使用 SetConsoleMode 禁用默认的回显行为(从而回显您自己的字符,如星号)。然后,您可以使用SetConsoleMode恢复回显。

但是,我应该补充一点,这是一种非常糟糕的身份验证形式,因为它涉及更多的密码,这是每个用户存在的祸根(也不是特别安全)。更好的方法是在应用程序中启动Web服务器并输出用户应在其上进行身份验证的URL。这种方法的优点是,当用户导航到此URL时,该URL可以支持委托登录到第三方身份提供商,例如Google,Facebook,Twitter等。即使您不支持第三方身份提供商,这种方法带来了其他好处;如果你有其他基于Web的工具,这种方法减少了用户必须进行身份验证的次数(因为命令行工具和基于Web的工具将共享相同的浏览器会话)并允许您只实现一次登录流程,这种方法还可以减轻网络钓鱼风险(用户可以在输入凭据时在浏览器中清楚地看到主机,而在命令行输入凭据更容易欺骗提示,并且如果您只在最后一步重定向到localhost但是远程主机上的大多数逻辑这种方法还允许独立于客户端命令行应用程序部署授权流的更新,这具有重要的安全性好处。也就是说,基于Web的登录并不总是正确的方法。还有值得研究其他身份验证机制,例如libpam(在libpam下,你会使用该函数 pam_authenticate 验证用户,而不是直接将密码作为输入)。值得投入一些研究来确定特定用例的最佳机制。


17
2017-09-23 09:07



对不起,你刚才建议OP从他的控制台应用程序输出一个到身份验证页面的URL ??? - Lightness Races in Orbit
@LightnessRacesinOrbit,是的,我做到了。是的,我知道这很不寻常和奇怪,但它是2014年...即使你在终端上打字,你仍然可以访问浏览器,这是正确和安全地实现委派登录的唯一方法,你可以请确保您的密码(在某些情况下,第二因素令牌)仅发送给身份提供者而不是控制台应用程序。 - Michael Aaron Safyan
@MichaelAaronSafyan安全性或用户体验的考虑远远超出了这个问题的范围,如果没有更多的上下文,你就无法以合理的方式解决这些问题。我建议你删除你的答案的最后一段,在这种情况下它是毫无意义的。 - Michael Le Barbier Grünewald
@MichaelGrünewald他们真的吗?工程学就是要理解权衡并理解与手头主题相关的更大背景和考虑因素。任何白痴都可以反复记忆批发的信息或在UNIX手册页中查找如何执行特定技术解决方案的信息。我相信,知道这是一个好主意还是可用的替代品也非常重要。而且,虽然您的建议可能并不总是适用,但我认为此建议为答案提供了额外的价值。 - Michael Aaron Safyan
@MichaelAaronSafyan暗示替代解决方案是一个有效点,但这不是你在做什么。相反,您将基于浏览器的第三方身份验证呈现为 举世 优于传统的密码认证,但事实并非如此。它只是一个独特的范例,具有明显的优势,缺点和适用性领域。没有更多的上下文说“X是一种非常形式的身份验证”和“更好的方法是Y”只会破坏你的信用,恕我直言。替代方法是无数的,我们可以引用 pam, ssh-keygen, kerberos,...帮助OP开始。 - Michael Le Barbier Grünewald


在Linux和其他一些类Unix平台上你可以使用 termios.h 为了这。您需要禁用echo end规范模式进行输出和打印 * 每个人得到角色后。 有C代码示例:

#include <termios.h>

struct termios term;

/* Disable echo input characters and buffered input by disabling ICANON*/
static void disable_echo() {
    struct termios new;
    if (tcgetattr(fileno(stdin), &term) != 0) {
        perror("tcgetattr failed");
        exit(-1);
    }

    new = term;
    new.c_lflag &= ~ICANON;
    new.c_lflag &= ~ECHO;
    if (tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0) {
        perror("tcsetattr failed");
        exit(-1);
    }
}

/* Enable normal terminal state after getting password*/
static void enable_echo() {
    if (tcsetattr(fileno(stdin), TCSAFLUSH, &term) != 0) {
        perror("tcsetattr failed");
        exit(-1);
    }
}

/* Read password which will be printed as `*` characters */
static void mask_getstr(char* buf, size_t size){
    char c = '\0';
    while (--size > 0 && (c = getchar()) != '\n') {
        *buf++ = c;
        putchar('*');
    }
    *buf = '\0';
}

0
2017-12-27 16:27





    #include<iostream.h>
    #include<stdio.h>
    #include<string.h>
    void main()
    {
     char str[10];
     int i=0,x,y;
     cout<<"enter : ";
     while(1)
      { str[i]=getch();
        if(str[i]==13)
        break;
        if(str[0]==127||str[0]==8)
        continue;
        if(str[i]==127||str[i]==8)
        {
           i--;
           x=wherex();
           y=wherey();
           gotoxy(x-1,y);
           clreol();
         }
         else
         {
           cout<<"*";
           i++;
         }
       }
     if(strcmp(str,"1234")==0)
     cout<<"Welcome";
     else
     cout<<"Try again";
    }

-1
2017-10-23 13:19