English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Implementación y aplicación por defecto del IPasswordHasher de Microsoft.Identity en ASP.net

Aquellos que conocen el sistema de autenticación MS Identity deben saber el papel de UserManager, que es el coordinador de todo el sistema. Define un conjunto de comportamientos de usuarios para ayudarnos a gestionar la información de usuarios, información de roles y manejar contraseñas. Su implementación se realiza en UserStore, donde podemos implementar lo que hemos definido, como IUserStore, IUserPasswordStore, IRoleStore, etc. Podemos basarnos en un conjunto completo de comportamientos de usuarios para personalizar nuestra información de usuarios y estructura de datos, así como el almacenamiento de datos. En cuanto al Hasher de contraseñas, MS también nos proporciona una definición completa de comportamientos, y es UserManager el que coordina. Por ejemplo

UserManager.PasswordHasher.HashPassword(password)

PasswordHasher se define en la interfaz UserManager de la siguiente manera:

Originalmente no tenía interés en su implementación predeterminada, por lo que, con el propósito de autenticación de inicio de sesión independiente de múltiples aplicaciones, se necesita un proyecto de autenticación de usuarios independiente como servicio de autenticación, que solo produce tokens. Después de la autenticación exitosa, el usuario debe acceder a los recursos en el servidor de aplicaciones utilizando el Header de Request HTTP Authorization con el token.

Por esta razón, en la autenticación de contraseñas de múltiples aplicaciones, se produjo este problema:

Por ejemplo, la aplicación A utiliza la implementación de IPasswordHasher para personalizar el método de cifrado - MD5+En forma de sal, mientras que la aplicación B utiliza el PasswordHasher predeterminado de Identity para implementar, obteniendo el siguiente código a través de la descompilación:

Por lo tanto, para ser compatible con diferentes métodos de cifrado en varias aplicaciones, tengo que descompilar el código fuente, obtener su método de cifrado predeterminado, juzgar según el nombre de la aplicación diferente si se debe cifrar o descifrar la contraseña, o directamente comparar de alguna manera la contraseña ingresada por el usuario con la base de datos. Primero, el implementación específica de PasswordHasher predeterminado de MS

// Descompilado con el descompilador JetBrains
// Tipo: Microsoft.AspNet.Identity.Crypto
// Assembly: Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: E3A10FFD-023A-4BC3-AD53-32D145ABF1C9
// Ubicación del ensamblado: C:\Sport\NewProject\V2.0\Api\Fantasy.Sport\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
namespace Microsoft.AspNet.Identity
{
 internal static class Crypto
 {
 private const int PBKDF2IterCount = 1000;
 private const int PBKDF2SubkeyLength = 32;
 private const int SaltSize = 16;
 public static string HashPassword(string password)
 {
  if (password == null)
  throw new ArgumentNullException("password");
  byte[] salt;
  byte[] bytes;
  using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, 16, 1000))
  {
  salt = rfc2898DeriveBytes.Salt;
  bytes = rfc2898DeriveBytes.GetBytes(32);
  }
  byte[] inArray = new byte[49];
  Buffer.BlockCopy((Array) salt, 0, (Array) inArray, 1, 16);
  Buffer.BlockCopy((Array) bytes, 0, (Array) inArray, 17, 32);
  return Convert.ToBase64String(inArray);
 }
 public static bool VerifyHashedPassword(string hashedPassword, string password)
 {
  if (hashedPassword == null)
  return false;
  if (password == null)
  throw new ArgumentNullException("password");
  byte[] numArray = Convert.FromBase64String(hashedPassword);
  if (numArray.Length != 49 || (int) numArray[0] != 0)
  return false;
  byte[] salt = new byte[16];
  Buffer.BlockCopy((Array) numArray, 1, (Array) salt, 0, 16);
  byte[] a = new byte[32];
  Buffer.BlockCopy((Array) numArray, 17, (Array) a, 0, 32);
  byte[] bytes;
  using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, 1000))
  bytes = rfc2898DeriveBytes.GetBytes(32);
  return Crypto.ByteArraysEqual(a, bytes);
 }
 [MethodImpl(MethodImplOptions.NoOptimization)]
 private static bool ByteArraysEqual(byte[] a, byte[] b)
 {
  if (object.ReferenceEquals((object) a, (object) b))
  return true;
  if (a == null || b == null || a.Length != b.Length)
  return false;
  bool flag = true;
  for (int index = 0; index < a.Length; ++index)
  flag &= (int) a[index] == (int) b[index];
  volver flag;
 }
 }
}

Alguien podría preguntar, ¿cómo se aplica esto a estos códigos fuente obtenidos? A continuación, se describe brevemente este problema.

Al principio, pensé que no era más que una encriptación, no tenía que verlo con tanto detalle, simplemente tomarlo y usarlo.

Al registrar usuarios y modificar contraseñas, siempre se realiza la encriptación de contraseñas a través del método HashPassword mencionado anteriormente. Entonces, en mi nuevo PasswordHasher personalizado, al comparar la contraseña de inicio de sesión del usuario con la aplicación B, ¿no sería mejor encriptar directamente la entrada del usuario a través de HashPassword? Por lo tanto, mi método personalizado VerifyHashedPassword (Verify se traduce como verificar) compara si el Pwd en la base de datos y el resultado procesado por el hasher son iguales. Pero el resultado es que, cada vez que se produce una cadena相同的字符串, se genera un resultado de encriptación diferente, y antes de jugar md5+La sal es diferente. Por lo tanto, pensé en el método de implementación predeterminado VerifyHashedPassword.

Por lo tanto, lo último que quiero decir es que puedes usar directamente el método de encriptación de Microsoft Identity (el Hasher mencionado anteriormente) y usar su método VerifyHashedPassword () al comparar la entrada del usuario con el resultado almacenado en la base de datos que ya ha sido hash. Incluso si no se usa autenticación Identity, se puede usar este algoritmo de encriptación.

Esto es todo el contenido de este artículo. Espero que el contenido de este artículo pueda proporcionar cierta ayuda a su aprendizaje o trabajo. También espero que apoyen más a la tutorial de gritos!

Declaración: El contenido de este artículo se ha obtenido de la red, y pertenece al propietario original. El contenido ha sido subido por usuarios de Internet de manera autónoma. Este sitio no posee los derechos de propiedad, no ha sido editado por humanos y no asume responsabilidad alguna por los litigios relacionados.3Declaración: Si encuentra contenido sospechoso de copyright, envíe un correo electrónico a notice#w para denunciar, proporcionando evidencia relevante. Una vez verificada, este sitio eliminará inmediatamente el contenido infractor.

Te gustará