当前位置: 首页 > 编程笔记 >

Asp.net中Microsoft.Identity的IPasswordHasher加密的默认实现与运用

周辉
2023-03-14
本文向大家介绍Asp.net中Microsoft.Identity的IPasswordHasher加密的默认实现与运用,包括了Asp.net中Microsoft.Identity的IPasswordHasher加密的默认实现与运用的使用技巧和注意事项,需要的朋友参考一下

相信了解了MS Identity认证体系的一定知道UserManager的作用,他是整个体系中的调度者,他定义了一套用户行为来帮助我们管理用户信息,角色信息,处理密码等。而其实现则在UserStore当中,我们可以实现其为我们定义的比如IUserStore,IUserPasswordStore,IRoleStore等等. 我们可以基于一整套用户行为,自定义自己的用户信息和数据结构以及数据存储。那么关于Password的Hasher,MS依然为我们提供了完整的行为定义,也由UserManager来调度。比如

UserManager.PasswordHasher.HashPassword(password)

PasswordHasher在UserManager接口中是这样定义的:

我原本对其默认实现是没有兴趣的,出于独立多个应用的登陆认证的目的,所以需要一个独立的用户认证项目来作为认证服务,其仅生产token,认证成功后,用户的HTTP Request Header的Authorization带着 token来访问应用服务器上的各种资源。

就是因为这样的原因,在多个应用的密码认证上出现了这样一个问题:

比如应用A采用了实现IPasswordHasher来自定义加密方式——MD5+salt的形式,而应用B则采用了Identity默认的PasswordHasher来实现,通过反编译得到如下代码

所以为了兼容多个应用不同的加密方式,我不得不反编译出源码,拿到其默认加密方式,根据不同应用名称,来判断对密码加密或者解密,或者直接通过某种方式来对比数据库和用户输入的密码。先上MS默认的PasswordHasher具体实现

// Decompiled with JetBrains decompiler
// Type: Microsoft.AspNet.Identity.Crypto
// Assembly: Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: E3A10FFD-023A-4BC3-AD53-32D145ABF1C9
// Assembly location: 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];
  return flag;
 }
 }
}

有人可能会问,拿到了这些源码要如何应用呢。下面就是浅述到这个问题。

一开始我天真的认为,不就是一个加密么,不用仔细看了,拿来用就好了?

在注册用户和修改密码的时候,都是通过上面 HashPassword 方法来做的密码加密,那我在新的自定义PasswordHasher中,为应用B对比用户登录密码的时候,把用户输入直接通过HashPassword加密一边不就好了?所以我自定义的VerifyHashedPassword (Verify译为核实)方法,就是比较数据库中的Pwd和经过hasher处理的结果是否相等。 可结果是,每次相同的字符串,会产生不同的加密结果,和以前玩md5+salt不一样呀。所以我又想到了其默认实现的  VerifyHashedPassword 方法。

所以最后要说的就是 你可以拿来微软Identity的加密方式(上面的Hasher)直接使用 , 在比较用户输入和数据库中已经经过hash的存储结果进行对比的时候,使用其 VerifyHashedPassword()方法。即使不使用Identity认证 也可以用此加密算法

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持小牛知识库!

 类似资料:
  • 本文向大家介绍ASP.NET中DES加密与解密MD5加密帮助类的实现代码,包括了ASP.NET中DES加密与解密MD5加密帮助类的实现代码的使用技巧和注意事项,需要的朋友参考一下     调用:               以上所述是小编给大家介绍的ASP.NET中DES加密与解密MD5加密帮助类,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对呐喊教程

  • 本文向大家介绍Kotlin 与默认实现接口,包括了Kotlin 与默认实现接口的使用技巧和注意事项,需要的朋友参考一下 示例 Kotlin中的接口可以具有功能的默认实现: 实现此类接口的类将能够使用这些功能而无需重新实现 物产 默认实现也适用于属性获取器和设置器: 接口访问器实现不能使用后备字段 多种实现 当多个接口实现相同的功能,或者所有接口都定义一个或多个实现时,派生类需要手动解析正确的调用

  • 本文向大家介绍ASP.Net Core3.0中使用JWT认证的实现,包括了ASP.Net Core3.0中使用JWT认证的实现的使用技巧和注意事项,需要的朋友参考一下 JWT认证简单介绍 关于Jwt的介绍网上很多,此处不在赘述,我们主要看看jwt的结构。 JWT主要由三部分组成,如下: HEADER 包含token的元数据,主要是加密算法,和签名的类型,如下面的信息,说明了 加密的对象类型是JWT

  • 我使用mysql aes加密和解密如下: 我读到AES支持128 192和256。我假设默认值是128是正确的吗?因此,鉴于上述查询没有定义密钥长度,它会以默认密钥长度加密和解密吗? 如果是这样,在上面的查询中指定密钥长度会更好吗?因为例如:假设我使用默认值128加密和存储数据,但后来设置更改,256变为默认值,那么这意味着它将无法解密数据,对吗?有没有办法在上面的查询中定义密钥长度? 另外,我用

  • 我想知道如果在创建用户或更改角色时没有指定ENCRYPTED,那么PostgreSQL使用的默认加密方法(如果有的话)是什么。 我在PostgreSQL网站上看到了以下内容: 密码存储加密默认情况下,数据库用户密码存储为MD5哈希,因此管理员无法确定分配给用户的实际密码。如果MD5加密用于客户端身份验证,则未加密的密码甚至不会暂时出现在服务器上,因为客户端MD5在通过网络发送之前对其进行加密。

  • 在此对话框,您可以输入默认的密码,这可应用在添加、解压、测试和查看选项时。 如果“显示密码”选项被禁用并且压缩文档操作时需要密码,您将会被要求输入密码两次来进行正确性的确认。 如果您设置了“加密文件名选项”,WinRAR 不只加密数据,而且加密所有包括文件数据、文件名、大小、属性、注释和其它块等所有可感知的压缩文件区域,所以它提供了更高的安全等级。在压缩文件中使用这个命令加密,没有密码甚至不可能查