Microsoft.Identity的IPasswordHasher加密的默认实现与运用
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址 www.cnblogs.com/tdws
相信了解了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 = ;
private const int PBKDF2SubkeyLength = ;
private const int SaltSize = ; public static string HashPassword(string password)
{
if (password == null)
throw new ArgumentNullException("password");
byte[] salt;
byte[] bytes;
using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, , ))
{
salt = rfc2898DeriveBytes.Salt;
bytes = rfc2898DeriveBytes.GetBytes();
}
byte[] inArray = new byte[];
Buffer.BlockCopy((Array) salt, , (Array) inArray, , );
Buffer.BlockCopy((Array) bytes, , (Array) inArray, , );
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 != || (int) numArray[] != )
return false;
byte[] salt = new byte[];
Buffer.BlockCopy((Array) numArray, , (Array) salt, , );
byte[] a = new byte[];
Buffer.BlockCopy((Array) numArray, , (Array) a, , );
byte[] bytes;
using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, ))
bytes = rfc2898DeriveBytes.GetBytes();
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 = ; 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认证 也可以用此加密算法。
如果需要更多了解Identity和OWIN,请看腾飞的如下四篇文章:
http://www.cnblogs.com/jesse2013/category/551550.html
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下加【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击下方红色【关注】的。
因为,我的分享热情也离不开您的肯定支持。
感谢您的阅读,我将持续输出分享,我是蜗牛, 保持学习,谨记谦虚。不端不装,有趣有梦。
Microsoft.Identity的IPasswordHasher加密的默认实现与运用的更多相关文章
- Microsoft.Identity的IPasswordHasher的默认实现与运用
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址 www.cnblogs.com/tdws 相信了解了MS Identity认证体系的一定知道UserManager的作用,他是整个体 ...
- (4.22)Microsoft 管理控制台启用 SSL 加密的 SQL Server 实例
如何通过使用 Microsoft 管理控制台启用 SSL 加密的 SQL Server 实例 关键词:MSSQL加密,sql server加密,sql server客户端与服务器传输内容加密 转自:h ...
- MVC6 OWin Microsoft Identity 自定义验证
1. Startup.cs中修改默认的验证设置 //app.UseIdentity(); app.UseCookieAuthentication(options => { //options.A ...
- ASP.NET没有魔法——ASP.NET Identity的加密与解密
前面文章介绍了如何使用Identity在ASP.NET MVC中实现用户的注册.登录以及身份验证.这些功能都是与用户信息安全相关的功能,数据安全的重要性永远放在第一位.那么对于注册和登录功能来说要把密 ...
- [转载] TLS协议分析 与 现代加密通信协议设计
https://blog.helong.info/blog/2015/09/06/tls-protocol-analysis-and-crypto-protocol-design/?from=time ...
- asp.net core系列 52 Identity 其它关注点
一.登录分析 在使用identity身份验证登录时,在login中调用的方法是: var result = await _signInManager.PasswordSignInAsync(Input ...
- (译)利用ASP.NET加密和解密Web.config中连接字符串
介绍 这篇文章我将介绍如何利用ASP.NET来加密和解密Web.config中连接字符串 背景描述 在以前的博客中,我写了许多关于介绍 Asp.net, Gridview, SQL Server, A ...
- 利用ASP.NET加密和解密Web.config中连接字符串
摘自:博客园 介绍 这篇文章我将介绍如何利用ASP.NET来加密和解密Web.config中连接字符串 背景描述 在以前的博客中,我写了许多关于介绍 Asp.net, Gridview, SQL Se ...
- Oracle 12C -- Identity Columns(标识列)
Identity Columns很适合数据库中需要"surrogate keys"的场景.依赖sequence产生器,每行的标识列会被赋予一个自增或自减的值.缺省,标识列在创建的时 ...
随机推荐
- hdu2896之AC自动机
病毒侵袭 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- AngularJS中巧用ngModel的$asyncValidators属性写一个验证唯一性的Direcitve
有这样的一个需求:添加用户的时候,根据主键判断当前添加用户的email是否已经被使用. 为此,我们需要把主键和email来传递给远程的一个API,让API返回结果,告之当前email是否被使用过. 写 ...
- uva 1629切蛋糕(dp)
有一个n行m列的网格蛋糕,上面有一些樱桃.求使得每块蛋糕上都有一个樱桃的分割最小长度 思路:dp. #include<cstdio> #include<cstring> #in ...
- WinPcap权威指南(一)
WinPcap是一个开源的网络抓包模块,顾名思义,它只能工作在Windows下,但本文介绍的知识并不局限于任何操作系统和开发语言,因为网络协议本身是没有这些区别的.阅读本指南之前,请先下载WinPca ...
- postgre 导出单表和导入
pg除了可以通过dump的方式导入和导出.如果只是导出数据,可以直接使用copy 导出 COPY user TO '/tmp/data/test.csv' WITH csv; COPY user(na ...
- eclipse maven 导出项目依赖的jar包
转自:https://blog.csdn.net/andyliulin/article/details/46544555 一.导出到默认目录 targed/dependency 从Maven项目中导出 ...
- java多线程有哪些实际的应用场景?
多线程使用的主要目的在于: 1.吞吐量:你做WEB,容器帮你做了多线程,但是他只能帮你做请求层面的.简单的说,可能就是一个请求一个线程.或多个请求一个线程.如果是单线程,那同时只能处理一个用户的请求. ...
- sqlite3命令行查看中文乱码问题解决
SQLite库包含一个名字叫做sqlite3的命令行,它可以让用户手工输入并执行面向SQLite数据库的SQL命令.我们通过程序创建的数据库一般位于/data/data/程序db设置的content类 ...
- Mac下打开多个eclipse
命令行执行: open -n /Eclipse所在路径/Eclipse.app
- virt-manager中为centos 7.2 扩容根分区
1. 打开virt-manager,添加一块磁盘. Add Hardware --> 选中Storage --> Manager (操作参考下图) 点击Manager之后,弹出Choose ...
