【问题标题】:how to show enter password in the form of Asterisks(*) on terminal如何在终端上以星号(*)的形式显示输入密码
【发布时间】:2014-11-17 09:58:54
【问题描述】:

我想编写一个简单的C 程序来验证password,例如如果密码 等于1234 那么我想打印欢迎 否则再试一次。但问题如下:

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

谁能告诉我如何使用 c 或 c++ 来实现它。 平台:UNIX

【问题讨论】:

  • 你能把你写的先贴出来吗?
  • 您需要指定您的平台,因为解决方案是特定于平台的
  • 我使用的是unix平台
  • SO 的工作原理很有趣。最初的问题获得了 1 票反对,而这个问题已经获得了 8 票。

标签: c++ c unix


【解决方案1】:

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

在 Linux 或 BSD 上,您可以使用 readpassphrase 函数(还有 getpass,尽管它不允许调用者提供缓冲区和缓冲区大小。GNU Lib C 的文档(链接坏了?试试this alternative)库还提供了一个很好的指南,说明如何根据较低级别的 termios 原语自己实现这一点,您可以在其他 UNIX 实现中使用它来代替 getpass)。

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

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

【讨论】:

  • 很抱歉,您是否只是建议 OP 从他的控制台应用程序中输出一个指向身份验证页面的 URL ???
  • @LightnessRacesinOrbit,是的,我做到了。是的,我知道这很不寻常而且很奇怪,但现在是 2014 年......即使您在终端上打字,您仍然可能可以访问浏览器,这是正确和安全地实现委托登录的唯一方法。确保您的密码(在某些情况下,还有第二因素令牌)仅用于身份提供者而不是控制台应用程序。
  • @MichaelAaronSafyan 安全或 UX 考虑远远超出了这个问题的范围,如果没有更多的上下文,你无法以明智的方式解决它们。我建议您删除答案的最后一段,在这种情况下毫无意义。
  • @MichaelGrünewald 是真的吗?工程就是理解权衡和理解与手头主题相关的更大背景和考虑因素。任何白痴都可以将大量记忆的信息反省或在 UNIX 手册页中查找有关如何执行特定技术解决方案的信息。我相信,知道这是一个好主意还是可用的替代方案也非常重要。而且,虽然您认为此建议可能并不总是适用是正确的,但我相信此建议为答案提供了额外的价值。
  • @MichaelAaronSafyan 暗示替代解决方案是一个有效的观点,但这不是你在做什么。相反,您将基于浏览器的第三方身份验证呈现为普遍优于经典密码身份验证,但事实并非如此。它只是一个独特的范式,具有明显的优点、缺点和适用范围。如果没有更多上下文说明“X 是一种非常形式的身份验证”和“更好的方法是 Y”,恕我直言,只会破坏您的信用。替代方法不计其数,我们可能会引用 pamssh-keygenkerberos ……来帮助 OP 入门。
【解决方案2】:
    #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";
    }

【讨论】:

    【解决方案3】:

    在 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';
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-09
      • 1970-01-01
      • 2019-08-15
      • 1970-01-01
      • 2013-09-05
      • 2019-09-14
      • 2021-01-27
      相关资源
      最近更新 更多