我尝试了下面的代码…

string pass = "";
Console.Write("Enter your password: ");
ConsoleKeyInfo key;

do
{
    key = Console.ReadKey(true);

    // Backspace Should Not Work
    if (key.Key != ConsoleKey.Backspace)
    {
        pass += key.KeyChar;
        Console.Write("*");
    }
    else
    {
        Console.Write("\b");
    }
}
// Stops Receving Keys Once Enter is Pressed
while (key.Key != ConsoleKey.Enter);

Console.WriteLine();
Console.WriteLine("The Password You entered is : " + pass);

但是这样的话,退格键在输入密码时就不起作用了。 任何建议吗?


当前回答

我在shermy的香草c# 3.5 . net解决方案中发现了一个bug,否则它会很有魅力。我还结合了Damian leszczyzynski - Vash的SecureString思想,但如果你喜欢,你可以使用普通字符串。

错误:如果在密码提示期间按退格键,并且当前密码长度为0,则在密码掩码中错误地插入了星号。要修复此错误,请修改以下方法。

    public static string ReadPassword(char mask)
    {
        const int ENTER = 13, BACKSP = 8, CTRLBACKSP = 127;
        int[] FILTERED = { 0, 27, 9, 10 /*, 32 space, if you care */ }; // const


        SecureString securePass = new SecureString();

        char chr = (char)0;

        while ((chr = System.Console.ReadKey(true).KeyChar) != ENTER)
        {
            if (((chr == BACKSP) || (chr == CTRLBACKSP)) 
                && (securePass.Length > 0))
            {
                System.Console.Write("\b \b");
                securePass.RemoveAt(securePass.Length - 1);

            }
            // Don't append * when length is 0 and backspace is selected
            else if (((chr == BACKSP) || (chr == CTRLBACKSP)) && (securePass.Length == 0))
            {
            }

            // Don't append when a filtered char is detected
            else if (FILTERED.Count(x => chr == x) > 0)
            {
            }

            // Append and write * mask
            else
            {
                securePass.AppendChar(chr);
                System.Console.Write(mask);
            }
        }

        System.Console.WriteLine();
        IntPtr ptr = new IntPtr();
        ptr = Marshal.SecureStringToBSTR(securePass);
        string plainPass = Marshal.PtrToStringBSTR(ptr);
        Marshal.ZeroFreeBSTR(ptr);
        return plainPass;
    }

其他回答

完整的解决方案,香草c# .net 3.5+

剪切粘贴 :)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace ConsoleReadPasswords
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.Write("Password:");

                string password = Orb.App.Console.ReadPassword();

                Console.WriteLine("Sorry - I just can't keep a secret!");
                Console.WriteLine("Your password was:\n<Password>{0}</Password>", password);

                Console.ReadLine();
            }
        }
    }

    namespace Orb.App
    {
        /// <summary>
        /// Adds some nice help to the console. Static extension methods don't exist (probably for a good reason) so the next best thing is congruent naming.
        /// </summary>
        static public class Console
        {
            /// <summary>
            /// Like System.Console.ReadLine(), only with a mask.
            /// </summary>
            /// <param name="mask">a <c>char</c> representing your choice of console mask</param>
            /// <returns>the string the user typed in </returns>
            public static string ReadPassword(char mask)
            {
                const int ENTER = 13, BACKSP = 8, CTRLBACKSP = 127;
                int[] FILTERED = { 0, 27, 9, 10 /*, 32 space, if you care */ }; // const

                var pass = new Stack<char>();
                char chr = (char)0;

                while ((chr = System.Console.ReadKey(true).KeyChar) != ENTER)
                {
                    if (chr == BACKSP)
                    {
                        if (pass.Count > 0)
                        {
                            System.Console.Write("\b \b");
                            pass.Pop();
                        }
                    }
                    else if (chr == CTRLBACKSP)
                    {
                        while (pass.Count > 0)
                        {
                            System.Console.Write("\b \b");
                            pass.Pop();
                        }
                    }
                    else if (FILTERED.Count(x => chr == x) > 0) { }
                    else
                    {
                        pass.Push((char)chr);
                        System.Console.Write(mask);
                    }
                }

                System.Console.WriteLine();

                return new string(pass.Reverse().ToArray());
            }

            /// <summary>
            /// Like System.Console.ReadLine(), only with a mask.
            /// </summary>
            /// <returns>the string the user typed in </returns>
            public static string ReadPassword()
            {
                return Orb.App.Console.ReadPassword('*');
            }
        }
    }

(我的)nuget包来做这个,基于上面的答案:

安装包PanoramicData。ConsoleExtensions

用法:

using PanoramicData.ConsoleExtensions;

...

Console.Write("Password: ");
var password = ConsolePlus.ReadPassword();
Console.WriteLine();

项目网址:https://github.com/panoramicdata/PanoramicData.ConsoleExtensions

欢迎拉请求。

我只是改进代码从问我简单,只是工作

    string pass = ""; //create empty password string
    Console.Write("Enter your password: ");
    ConsoleKeyInfo key;
    int passLen = 0; // base password length

    do
    {
        key = Console.ReadKey(true); //reading keyboard key

        if (key.Key == ConsoleKey.Escape) Environment.Exit(0); // If key is escape console will close (optional)

        if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter) // on key with is not bacspase and enter 
        {
            pass += key.KeyChar; //password string add key value
            Console.Write("*"); // and print star as masked char 
            passLen++; // upgrading password length
        }
        else if (passLen > 0 && key.Key == ConsoleKey.Backspace) //if password have a any symbol and u press Backspace
        {   
                Console.Write("\b \b"); //Backspace delete star symbol and coursor back in line 
                passLen--; // password length is one less
                pass = pass[0..^1]; // new string passowrd is string without last charter 
        }
    } 
    while (key.Key != ConsoleKey.Enter); // if you press enter this stop execute with your password

    Console.WriteLine();
    Console.WriteLine("The Password You entered is : " + pass);

这将用一个红色方块掩盖密码,然后在输入密码后恢复到原来的颜色。

它不会阻止用户使用复制/粘贴来获取密码,但如果它只是为了阻止别人从你的身后看,这是一个很好的快速解决方案。

Console.Write("Password ");
ConsoleColor origBG = Console.BackgroundColor; // Store original values
ConsoleColor origFG = Console.ForegroundColor;

Console.BackgroundColor = ConsoleColor.Red; // Set the block colour (could be anything)
Console.ForegroundColor = ConsoleColor.Red;

string Password = Console.ReadLine(); // read the password

Console.BackgroundColor= origBG; // revert back to original
Console.ForegroundColor= origFG;

下面是我的简单版本。 每次你按下一个键,从控制台删除所有,并绘制尽可能多的'*'作为密码字符串的长度。

int chr = 0;
string pass = "";
const int ENTER = 13;
const int BS = 8;

do
{
   chr = Console.ReadKey().KeyChar;
   Console.Clear(); //imediately clear the char you printed

   //if the char is not 'return' or 'backspace' add it to pass string
   if (chr != ENTER && chr != BS) pass += (char)chr;

   //if you hit backspace remove last char from pass string
   if (chr == BS) pass = pass.Remove(pass.Length-1, 1);

   for (int i = 0; i < pass.Length; i++)
   {
      Console.Write('*');
   }
} 
 while (chr != ENTER);

Console.Write("\n");
Console.Write(pass);

Console.Read(); //just to see the pass