Application de console de masquage de mot de passe

J’ai essayé le code suivant …

ssortingng 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); 

Mais de cette façon, la fonctionnalité de retour arrière ne fonctionne pas lors de la saisie du mot de passe. Toute suggestion?

    Console.Write("\b \b"); supprimera le caractère astérisque de l’écran, mais vous n’avez pas de code dans votre bloc else qui supprime le caractère précédemment saisi de votre variable de chaîne de pass .

    Voici la partie du code appropriée (la section if..else ) qui devrait faire ce dont vous avez besoin:

     // Backspace Should Not Work if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter) { pass += key.KeyChar; Console.Write("*"); } else { if (key.Key == ConsoleKey.Backspace && pass.Length > 0) { pass = pass.Subssortingng(0, (pass.Length - 1)); Console.Write("\b \b"); } } 

    Pour cela, vous devez utiliser le System.Security.SecureSsortingng

     public SecureSsortingng GetPassword() { var pwd = new SecureSsortingng(); while (true) { ConsoleKeyInfo i = Console.ReadKey(true); if (i.Key == ConsoleKey.Enter) { break; } else if (i.Key == ConsoleKey.Backspace) { if (pwd.Length > 0) { pwd.RemoveAt(pwd.Length - 1); Console.Write("\b \b"); } } else if (i.KeyChar != '\u0000' ) // KeyChar == '\u0000' if the key pressed does not correspond to a printable character, eg F1, Pause-Break, etc { pwd.AppendChar(i.KeyChar); Console.Write("*"); } } return pwd; } 

    Solution complète, vanille C # .net 3.5+

    Couper coller 🙂

      using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleReadPasswords { class Program { static void Main(ssortingng[] args) { Console.Write("Password:"); ssortingng password = Orb.App.Console.ReadPassword(); Console.WriteLine("Sorry - I just can't keep a secret!"); Console.WriteLine("Your password was:\n{0}", password); Console.ReadLine(); } } } namespace Orb.App { ///  /// 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. ///  static public class Console { ///  /// Like System.Console.ReadLine(), only with a mask. ///  /// a char representing your choice of console mask /// the ssortingng the user typed in  public static ssortingng 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 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 ssortingng(pass.Reverse().ToArray()); } ///  /// Like System.Console.ReadLine(), only with a mask. ///  /// the ssortingng the user typed in  public static ssortingng ReadPassword() { return Orb.App.Console.ReadPassword('*'); } } } 

    Prendre la meilleure réponse, ainsi que les suggestions de ses commentaires, et la modifier pour utiliser SecureSsortingng au lieu de Ssortingng, testez toutes les clés de contrôle, et non l’erreur ou écrivez un “*” supplémentaire à l’écran lorsque la longueur du mot de passe est 0. ma solution est:

     public static SecureSsortingng getPasswordFromConsole(Ssortingng displayMessage) { SecureSsortingng pass = new SecureSsortingng(); Console.Write(displayMessage); ConsoleKeyInfo key; do { key = Console.ReadKey(true); // Backspace Should Not Work if (!char.IsControl(key.KeyChar)) { pass.AppendChar(key.KeyChar); Console.Write("*"); } else { if (key.Key == ConsoleKey.Backspace && pass.Length > 0) { pass.RemoveAt(pass.Length - 1); Console.Write("\b \b"); } } } // Stops Receving Keys Once Enter is Pressed while (key.Key != ConsoleKey.Enter); return pass; } 

    Mine ignore les caractères de contrôle et gère le retour à la ligne:

     public static ssortingng ReadLineMasked(char mask = '*') { var sb = new SsortingngBuilder(); ConsoleKeyInfo keyInfo; while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Enter) { if (!char.IsControl(keyInfo.KeyChar)) { sb.Append(keyInfo.KeyChar); Console.Write(mask); } else if (keyInfo.Key == ConsoleKey.Backspace && sb.Length > 0) { sb.Remove(sb.Length - 1, 1); if (Console.CursorLeft == 0) { Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1); Console.Write(' '); Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1); } else Console.Write("\b \b"); } } Console.WriteLine(); return sb.ToSsortingng(); } 

    La lecture de l’entrée de la console est difficile, vous devez gérer des touches spéciales comme Ctrl, Alt, ainsi que les touches du curseur et Backspace / Delete. Sur certaines configurations de clavier, comme Swedish Ctrl, il est même nécessaire d’entrer des touches qui existent directement sur le clavier américain. Je pense qu’essayer de gérer cela en utilisant le “low-level” Console.ReadKey(true) est très difficile, donc le moyen le plus simple et le plus robuste est de simplement désactiver “echo d’entrée de console” lors de la saisie du mot de passe avec un peu de WINAPI .

    L’échantillon ci-dessous est basé sur la réponse à Read a password from std :: cin question.

      private enum StdHandle { Input = -10, Output = -11, Error = -12, } private enum ConsoleMode { ENABLE_ECHO_INPUT = 4 } [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetStdHandle(StdHandle nStdHandle); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out int lpMode); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetConsoleMode(IntPtr hConsoleHandle, int dwMode); public static ssortingng ReadPassword() { IntPtr stdInputHandle = GetStdHandle(StdHandle.Input); if (stdInputHandle == IntPtr.Zero) { throw new InvalidOperationException("No console input"); } int previousConsoleMode; if (!GetConsoleMode(stdInputHandle , out previousConsoleMode)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not get console mode."); } // disable console input echo if (!SetConsoleMode(stdInputHandle , previousConsoleMode & ~(int)ConsoleMode.ENABLE_ECHO_INPUT)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not disable console input echo."); } // just read the password using standard Console.ReadLine() ssortingng password = Console.ReadLine(); // reset console mode to previous if (!SetConsoleMode(stdInputHandle , previousConsoleMode)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not reset console mode."); } return password; } 

    Cela masque le mot de passe avec un carré rouge, puis revient aux couleurs d’origine une fois le mot de passe entré.

    Cela n’empêche pas l’utilisateur d’utiliser le copier / coller pour obtenir le mot de passe, mais s’il s’agit simplement d’empêcher quelqu’un de regarder par-dessus votre épaule, c’est une solution rapide.

     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; ssortingng Password = Console.ReadLine(); // read the password Console.BackgroundColor= origBG; // revert back to original Console.ForegroundColor= origFG; 

    J’ai trouvé un bogue dans la solution C # 3.5 .NET de vanille de Shermy qui fonctionne autrement. J’ai également intégré l’idée de SecureSsortingng de Vash dans Damian Leszczyński – mais vous pouvez utiliser une chaîne ordinaire si vous préférez.

    LE BOGUE: Si vous appuyez sur la touche Retour arrière pendant l’invite du mot de passe et que la longueur actuelle du mot de passe est 0, un astérisque est incorrectement inséré dans le masque de mot de passe. Pour corriger ce bogue, modifiez la méthode suivante.

      public static ssortingng ReadPassword(char mask) { const int ENTER = 13, BACKSP = 8, CTRLBACKSP = 127; int[] FILTERED = { 0, 27, 9, 10 /*, 32 space, if you care */ }; // const SecureSsortingng securePass = new SecureSsortingng(); 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.SecureSsortingngToBSTR(securePass); ssortingng plainPass = Marshal.PtrToSsortingngBSTR(ptr); Marshal.ZeroFreeBSTR(ptr); return plainPass; } 

    Vous pouvez append vos clés à une liste chaînée cumulative.

    Lorsqu’une touche de retour arrière est reçue, supprimez la dernière clé de la liste.

    Lorsque vous recevez la touche Entrée, réduisez votre liste en une chaîne et faites le rest de votre travail.

    J’ai fait quelques changements pour le retour arrière

      ssortingng 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 { pass = pass.Remove(pass.Length - 1); Console.Write("\b \b"); } } // Stops Receving Keys Once Enter is Pressed while (key.Key != ConsoleKey.Enter); Console.WriteLine(); Console.WriteLine("The Password You entered is : " + pass); 

    J’ai mis à jour la version de Ronnie après avoir passé beaucoup trop de temps à essayer de saisir un mot de passe uniquement pour découvrir que mon locking de majuscule était activé!

    Avec cette version, le message dans _CapsLockMessage sera “flottant” à la fin de la zone de saisie et sera affiché en rouge.

    Cette version prend un peu plus de code et requirejs une boucle d’interrogation. Sur mon ordinateur, le processeur consum environ 3% à 4%, mais vous pouvez toujours append une petite valeur Sleep () pour réduire l’utilisation du processeur si nécessaire.

      private const ssortingng _CapsLockMessage = " CAPS LOCK"; ///  /// Like System.Console.ReadLine(), only with a mask. ///  /// a char representing your choice of console mask /// the ssortingng the user typed in public static ssortingng ReadLineMasked(char mask = '*') { // Taken from http://stackoverflow.com/a/19770778/486660 var consoleLine = new SsortingngBuilder(); ConsoleKeyInfo keyInfo; bool isDone; bool isAlreadyLocked; bool isCapsLockOn; int cursorLeft; int cursorTop; ConsoleColor originalForegroundColor; isDone = false; isAlreadyLocked = Console.CapsLock; while (isDone == false) { isCapsLockOn = Console.CapsLock; if (isCapsLockOn != isAlreadyLocked) { if (isCapsLockOn) { cursorLeft = Console.CursorLeft; cursorTop = Console.CursorTop; originalForegroundColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.Write("{0}", _CapsLockMessage); Console.SetCursorPosition(cursorLeft, cursorTop); Console.ForegroundColor = originalForegroundColor; } else { cursorLeft = Console.CursorLeft; cursorTop = Console.CursorTop; Console.Write("{0}", ssortingng.Empty.PadRight(_CapsLockMessage.Length)); Console.SetCursorPosition(cursorLeft, cursorTop); } isAlreadyLocked = isCapsLockOn; } if (Console.KeyAvailable) { keyInfo = Console.ReadKey(intercept: true); if (keyInfo.Key == ConsoleKey.Enter) { isDone = true; continue; } if (!char.IsControl(keyInfo.KeyChar)) { consoleLine.Append(keyInfo.KeyChar); Console.Write(mask); } else if (keyInfo.Key == ConsoleKey.Backspace && consoleLine.Length > 0) { consoleLine.Remove(consoleLine.Length - 1, 1); if (Console.CursorLeft == 0) { Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1); Console.Write(' '); Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1); } else { Console.Write("\b \b"); } } if (isCapsLockOn) { cursorLeft = Console.CursorLeft; cursorTop = Console.CursorTop; originalForegroundColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.Write("{0}", _CapsLockMessage); Console.CursorLeft = cursorLeft; Console.CursorTop = cursorTop; Console.ForegroundColor = originalForegroundColor; } } } Console.WriteLine(); return consoleLine.ToSsortingng(); } 

    Voici ma version simple. Chaque fois que vous appuyez sur une touche, supprimez tout de la console et dessinez autant de ‘*’ que la longueur de la chaîne de mot de passe.

     int chr = 0; ssortingng 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 ssortingng if (chr != ENTER && chr != BS) pass += (char)chr; //if you hit backspace remove last char from pass ssortingng 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 

    Si je comprends bien, vous essayez de faire en sorte que backspace supprime à la fois le caractère visible * à l’écran et le caractère mis en cache dans votre variable pass?

    Si oui, alors changez simplement votre bloc à ceci:

      else { Console.Write("\b"); pass = pass.Remove(pass.Length -1); } 
      ssortingng pass = ""; Console.WriteLine("Enter your password: "); ConsoleKeyInfo key; do { key = Console.ReadKey(true); if (key.Key != ConsoleKey.Backspace) { pass += key.KeyChar; Console.Write("*"); } else { Console.Write("\b \b"); char[] pas = pass.ToCharArray(); ssortingng temp = ""; for (int i = 0; i < pass.Length - 1; i++) { temp += pas[i]; } pass = temp; } } // Stops Receving Keys Once Enter is Pressed while (key.Key != ConsoleKey.Enter); Console.WriteLine(); Console.WriteLine("The Password You entered is : " + pass);