Asp.net中Microsoft.Identity的IPasswordHasher加密的默認(rèn)實(shí)現(xiàn)與運(yùn)用
相信了解了MS Identity認(rèn)證體系的一定知道UserManager的作用,他是整個(gè)體系中的調(diào)度者,他定義了一套用戶行為來幫助我們管理用戶信息,角色信息,處理密碼等。而其實(shí)現(xiàn)則在UserStore當(dāng)中,我們可以實(shí)現(xiàn)其為我們定義的比如IUserStore,IUserPasswordStore,IRoleStore等等. 我們可以基于一整套用戶行為,自定義自己的用戶信息和數(shù)據(jù)結(jié)構(gòu)以及數(shù)據(jù)存儲(chǔ)。那么關(guān)于Password的Hasher,MS依然為我們提供了完整的行為定義,也由UserManager來調(diào)度。比如
UserManager.PasswordHasher.HashPassword(password)
PasswordHasher在UserManager接口中是這樣定義的:
我原本對(duì)其默認(rèn)實(shí)現(xiàn)是沒有興趣的,出于獨(dú)立多個(gè)應(yīng)用的登陸認(rèn)證的目的,所以需要一個(gè)獨(dú)立的用戶認(rèn)證項(xiàng)目來作為認(rèn)證服務(wù),其僅生產(chǎn)token,認(rèn)證成功后,用戶的HTTP Request Header的Authorization帶著 token來訪問應(yīng)用服務(wù)器上的各種資源。
就是因?yàn)檫@樣的原因,在多個(gè)應(yīng)用的密碼認(rèn)證上出現(xiàn)了這樣一個(gè)問題:
比如應(yīng)用A采用了實(shí)現(xiàn)IPasswordHasher來自定義加密方式——MD5+salt的形式,而應(yīng)用B則采用了Identity默認(rèn)的PasswordHasher來實(shí)現(xiàn),通過反編譯得到如下代碼:
所以為了兼容多個(gè)應(yīng)用不同的加密方式,我不得不反編譯出源碼,拿到其默認(rèn)加密方式,根據(jù)不同應(yīng)用名稱,來判斷對(duì)密碼加密或者解密,或者直接通過某種方式來對(duì)比數(shù)據(jù)庫和用戶輸入的密碼。先上MS默認(rèn)的PasswordHasher具體實(shí)現(xiàn)
// 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; } } }
有人可能會(huì)問,拿到了這些源碼要如何應(yīng)用呢。下面就是淺述到這個(gè)問題。
一開始我天真的認(rèn)為,不就是一個(gè)加密么,不用仔細(xì)看了,拿來用就好了?
在注冊(cè)用戶和修改密碼的時(shí)候,都是通過上面 HashPassword 方法來做的密碼加密,那我在新的自定義PasswordHasher中,為應(yīng)用B對(duì)比用戶登錄密碼的時(shí)候,把用戶輸入直接通過HashPassword加密一邊不就好了?所以我自定義的VerifyHashedPassword (Verify譯為核實(shí))方法,就是比較數(shù)據(jù)庫中的Pwd和經(jīng)過hasher處理的結(jié)果是否相等。 可結(jié)果是,每次相同的字符串,會(huì)產(chǎn)生不同的加密結(jié)果,和以前玩md5+salt不一樣呀。所以我又想到了其默認(rèn)實(shí)現(xiàn)的 VerifyHashedPassword 方法。
所以最后要說的就是 你可以拿來微軟Identity的加密方式(上面的Hasher)直接使用 , 在比較用戶輸入和數(shù)據(jù)庫中已經(jīng)經(jīng)過hash的存儲(chǔ)結(jié)果進(jìn)行對(duì)比的時(shí)候,使用其 VerifyHashedPassword()方法。即使不使用Identity認(rèn)證 也可以用此加密算法
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- ASP.NET MVC結(jié)合JavaScript登錄、校驗(yàn)和加密
- asp.net的加密解密技巧
- ASP.NET加密解密算法分享
- 在asp.net中使用加密數(shù)據(jù)庫聯(lián)接字符串保證數(shù)據(jù)安全
- asp.net實(shí)現(xiàn)md5加密
- 在ASP.Net中實(shí)現(xiàn)RSA加密的方法
- 解析Asp.net,C# 純數(shù)字加密解密字符串的應(yīng)用
- Asp.net,C# 加密解密字符串的使用詳解
- ASP.NET加密口令的方法實(shí)例
- asp.net中使用cookie與md5加密實(shí)現(xiàn)記住密碼功能的實(shí)現(xiàn)代碼
相關(guān)文章
在.ashx文件中獲取cookies值實(shí)現(xiàn)代碼
.ashx文件中獲取cookies值對(duì)于一些高手們就不多說了,至于一些小白們還是有必要多多學(xué)習(xí)啊,好了話不多說,看代碼,感興趣的你可不要錯(cuò)過了哈2013-02-02為密碼文本框要求不可粘帖字符串只可手動(dòng)輸入(附演示動(dòng)畫)
以前開發(fā)程序時(shí),用戶登錄的密碼文本框,是可以粘帖密碼字符串的,為了安全起見用戶要求不要粘帖,只能由手動(dòng)輸入,感興趣的朋友可以了解下2013-01-01ASP.NET:一段比較經(jīng)典的多線程學(xué)習(xí)代碼
ASP.NET:一段比較經(jīng)典的多線程學(xué)習(xí)代碼...2006-09-09解決ASP.NET Core Mvc文件上傳限制問題實(shí)例
本篇文章主要介紹了解決ASP.NET Core Mvc文件上傳限制問題,具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11ASP.NET 應(yīng)用程序級(jí) 驗(yàn)證用戶是否登錄 一般處理程序
驗(yàn)證用戶登錄后才能訪問頁面和進(jìn)行操作的方法有好幾種,比如:Forms,基類中處理、窗體類繼承基類,單獨(dú)寫個(gè)方法在每個(gè)窗體類的Page_Load中調(diào)用等。2010-07-07.NET Core API CORS的實(shí)現(xiàn)
這篇文章主要介紹了.NET Core API CORS的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08asp.net錯(cuò)誤處理Application_Error事件示例
Application_Error事件與Page_Error事件相類似,可使用他捕獲發(fā)生在應(yīng)用程序中的錯(cuò)誤。由于事件發(fā)生在整個(gè)應(yīng)用程序范圍內(nèi),因此您可記錄應(yīng)用程序的錯(cuò)誤信息或處理其他可能發(fā)生的應(yīng)用程序級(jí)別的錯(cuò)誤2014-01-01