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

Implementação padrão e uso do IPasswordHasher da Microsoft.Identity no Asp.net

Quem entende o sistema de autenticação MS Identity deve saber a função do UserManager, ele é o coordinador da estrutura inteira, ele define um conjunto de comportamentos de usuário para nos ajudar a gerenciar informações de usuário, informações de papel, lidar com senhas, etc. E sua implementação está no UserStore, podemos implementar o que ele define, como IUserStore, IUserPasswordStore, IRoleStore, etc. Podemos basear-nos em um conjunto completo de comportamentos de usuário, personalizar nossas informações de usuário e estrutura de dados e armazenamento de dados. Assim, sobre o Hasher de Senha, MS ainda nos fornece uma definição completa de comportamento, e é gerenciado pelo UserManager. Por exemplo

UserManager.PasswordHasher.HashPassword(password)

PasswordHasher é definido da seguinte maneira no interface UserManager:

Eu não estava interessado na implementação padrão original, então, por motivo de independentemente autenticar o login de várias aplicações, precisei de um projeto de autenticação de usuário independente como serviço de autenticação, que apenas gera tokens, e após a autenticação bem-sucedida, o usuário acessa os recursos de servidores de aplicações com o header de Authorization do HTTP Request levando o token.

Devido a essa razão, surgiu esse problema no autenticação de senha em várias aplicações:

Por exemplo, a aplicação A adotou a implementação de IPasswordHasher para personalizar o método de criptografia - MD5+Na forma de sal, enquanto a aplicação B adotou o PasswordHasher padrão do Identity para implementação, obtendo o seguinte código através da descompilação:

Portanto, para garantir a compatibilidade com diferentes métodos de criptografia de várias aplicações, tenho que descompilar o código-fonte, obter o método de criptografia padrão, determinar a criptografia ou descriptografia com base no nome da aplicação, ou diretamente comparar a senha inserida no banco de dados com a senha fornecida pelo usuário. Vamos ver a implementação específica do PasswordHasher padrão do MS.

// Descompilado com o decompiler do JetBrains
// Tipo: Microsoft.AspNet.Identity.Crypto
// Assembly: Microsoft.AspNet.Identity.Core, Versão=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: E3A10FFD-023A-4BC3-AD53-32D145ABF1C9
// Localização do assembly: C:\Sport\NovoProjeto\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];
  return flag;
 }
 }
}

Alguém pode perguntar como aplicar esses códigos-fonte. Abaixo é uma breve descrição dessa questão.

No início, eu achei que era só uma criptografia, não precisava olhar com atenção, poderia usar diretamente?

Quando você registra um usuário e modifica uma senha, é feito a criptografia da senha através do método HashPassword acima. Portanto, quando eu comparo a senha de login do usuário no novo PasswordHasher personalizado, por que não criptografar a entrada do usuário diretamente com HashPassword? Portanto, o meu método VerifyHashedPassword (Verify traduzido como verificar) compara se o Pwd no banco de dados e o resultado processado pelo hasher são iguais. No entanto, o resultado é que, a cada vez que a string é a mesma, gera diferentes resultados de criptografia, e antes de jogar md5+A salt é diferente. Portanto, eu pensei na implementação padrão VerifyHashedPassword.

Portanto, o que temos para dizer por último é que você pode usar diretamente o método de criptografia do Microsoft Identity (o Hasher acima) para comparar a entrada do usuário com o resultado armazenado hashado no banco de dados, usando o método VerifyHashedPassword () ao comparar. Mesmo que você não use autenticação Identity, você também pode usar este algoritmo de criptografia

Isso é tudo o que há no artigo, espero que o conteúdo deste artigo ajude você a aprender ou a trabalhar, e também espero que você dê mais suporte ao tutorial Yell!

Declaração: O conteúdo deste artigo é extraído da internet, pertence ao autor original, o conteúdo é contribuído e carregado voluntariamente pelos usuários da internet, este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidade legal. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#w3Declaração: O conteúdo deste artigo é extraído da internet, pertence ao autor original, o conteúdo é contribuído e carregado voluntariamente pelos usuários da internet, este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidade legal. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#w

Você também pode gostar