Microsoft.Identity的IPasswordHasher加密的預設實現與運用

来源:http://www.cnblogs.com/tdws/archive/2017/02/17/6409650.html
-Advertisement-
Play Games

本文版權歸博客園和作者吳雙本人共同所有,轉載和爬蟲請註明原文地址 www.cnblogs.com/tdws 相信瞭解了MS Identity認證體系的一定知道UserManager的作用,他是整個體系中的調度者,他定義了一套用戶行為來幫助我們管理用戶信息,角色信息,處理密碼等。而其實現則在UserS ...


 本文版權歸博客園和作者吳雙本人共同所有,轉載和爬蟲請註明原文地址  www.cnblogs.com/tdws

   相信瞭解了MS Identity認證體系的一定知道UserManager的作用,他是整個體系中的調度者,他定義了一套用戶行為來幫助我們管理用戶信息,角色信息,處理密碼等。而其實現則在UserStore當中,我們可以實現其為我們定義的比如IUserStore,IUserPasswordStore,IRoleStore等等. 我們可以基於一整套用戶行為,自定義自己的用戶信息和數據結構以及數據存儲。那麼關於Password的Hasher,MS依然為我們提供了完整的行為定義,也由UserManager來調度。比如

1 UserManager.PasswordHasher.HashPassword(password)
PasswordHasher在UserManager介面中是這樣定義的:

我原本對其預設實現是沒有興趣的,出於獨立多個應用的登陸認證的目的,所以需要一個獨立的用戶認證項目來作為認證服務,其僅生產token,認證成功後,用戶的HTTP Request Header的Authorization帶著 token來訪問應用伺服器上的各種資源。

就是因為這樣的原因,在多個應用的密碼認證上出現了這樣一個問題:

比如應用A採用了實現IPasswordHasher來自定義加密方式——MD5+salt的形式,而應用B則採用了Identity預設的PasswordHasher來實現,通過反編譯得到如下代碼:

所以為了相容多個應用不同的加密方式,我不得不反編譯出源碼,拿到其預設加密方式,根據不同應用名稱,來判斷對密碼加密或者解密,或者直接通過某種方式來對比資料庫和用戶輸入的密碼。先上MS預設的PasswordHasher具體實現

 1 // Decompiled with JetBrains decompiler
 2 // Type: Microsoft.AspNet.Identity.Crypto
 3 // Assembly: Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
 4 // MVID: E3A10FFD-023A-4BC3-AD53-32D145ABF1C9
 5 // 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
 6 
 7 using System;
 8 using System.Runtime.CompilerServices;
 9 using System.Security.Cryptography;
10 
11 namespace Microsoft.AspNet.Identity
12 {
13   internal static class Crypto
14   {
15     private const int PBKDF2IterCount = 1000;
16     private const int PBKDF2SubkeyLength = 32;
17     private const int SaltSize = 16;
18 
19     public static string HashPassword(string password)
20     {
21       if (password == null)
22         throw new ArgumentNullException("password");
23       byte[] salt;
24       byte[] bytes;
25       using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, 16, 1000))
26       {
27         salt = rfc2898DeriveBytes.Salt;
28         bytes = rfc2898DeriveBytes.GetBytes(32);
29       }
30       byte[] inArray = new byte[49];
31       Buffer.BlockCopy((Array) salt, 0, (Array) inArray, 1, 16);
32       Buffer.BlockCopy((Array) bytes, 0, (Array) inArray, 17, 32);
33       return Convert.ToBase64String(inArray);
34     }
35 
36     public static bool VerifyHashedPassword(string hashedPassword, string password)
37     {
38       if (hashedPassword == null)
39         return false;
40       if (password == null)
41         throw new ArgumentNullException("password");
42       byte[] numArray = Convert.FromBase64String(hashedPassword);
43       if (numArray.Length != 49 || (int) numArray[0] != 0)
44         return false;
45       byte[] salt = new byte[16];
46       Buffer.BlockCopy((Array) numArray, 1, (Array) salt, 0, 16);
47       byte[] a = new byte[32];
48       Buffer.BlockCopy((Array) numArray, 17, (Array) a, 0, 32);
49       byte[] bytes;
50       using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, 1000))
51         bytes = rfc2898DeriveBytes.GetBytes(32);
52       return Crypto.ByteArraysEqual(a, bytes);
53     }
54 
55     [MethodImpl(MethodImplOptions.NoOptimization)]
56     private static bool ByteArraysEqual(byte[] a, byte[] b)
57     {
58       if (object.ReferenceEquals((object) a, (object) b))
59         return true;
60       if (a == null || b == null || a.Length != b.Length)
61         return false;
62       bool flag = true;
63       for (int index = 0; index < a.Length; ++index)
64         flag &= (int) a[index] == (int) b[index];
65       return flag;
66     }
67   }
68 }

有人可能會問,拿到了這些源碼要如何應用呢。下麵就是淺述到這個問題。

一開始我天真的認為,不就是一個加密麽,不用仔細看了,拿來用就好了?

在註冊用戶和修改密碼的時候,都是通過上面 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

 

 

如果,您認為閱讀這篇博客讓您有些收穫,不妨點擊一下右下加推薦按鈕。
如果,您希望更容易地發現我的新博客,不妨點擊下方紅色【關註】的。
因為,我的分享熱情也離不開您的肯定支持。

感謝您的閱讀,我將持續輸出分享,我是蝸牛, 保持學習,謹記謙虛。不端不裝,有趣有夢。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • EF雖然是一個晚生畸形的ORM框架,但功能強大又具有靈活性的,給了開發人員一定的發揮空間。因為微軟出發點總是好的,讓開發變得簡單,但實際上不是所有的事情都這麼理想。這裡順便推薦馬丁大叔的書《企業應架構模式》。 本節主要深入分析EF的分層問題,下麵是本節的已列出的要探討內容。 領域模型的概念 DbCo ...
  • 導航 閱讀本文之前,您也可以到Asp.Net Web API 2 系列導航進行查看 http://www.cnblogs.com/aehyok/p/3446289.html。 本文主要來講解以下內容: 〇、前言 Ⅰ、Using[FromUri] Ⅱ、Using[FromBody] Ⅲ、Type Co ...
  • 本文的主要內容是通過兩種方式實現簡單郵件的接收,一種方式是通過C語言實現,另一種是通過C#實現的, 兩種方式在實現上有許多的不同之處,但是本質上都是一樣的. 一,C語言實現方式 C語言接收郵件的步驟: 1.創建TCP連接 埠:預設110 2.連接到Pop3伺服器 伺服器名稱:例如"pop3.163 ...
  • 浪漫的周末從cnblogs開始。話說,今天和往常的周末一樣,韓君躲在被窩裡用手機翻閱著園子里的珠璣。一篇《應用XML作為資料庫的快速開發框架》的文章在韓君腦子裡激起了一波球形閃電。想想上周中剛好完成的一個WinCE小項目,這波久久不能平息。韓君做了一個比馬兄更艱難的決定,秒速穿戴衣褲後,開始了那第N ...
  • EF Core 1.0 Database First http://www.cnblogs.com/linezero/p/EFCoreDBFirst.html ASP.NET Core 開發 - Entity Framework (EF) Core,ASP.NET Core 操作資料庫。 Entit ...
  • 今後爭取每兩天能更新一次。平日的誘惑太多,雙休只顧玩了,進度有點慢。 接上一講的,類型的安全性,留下了點小尾巴——比較對象的相等性。 C#有四種比較相等的方式:除了“==”運算符外,System.Object定義了3中方法:ReferenceEqual()方法和兩種Equals(); 1.首先是“= ...
  • 前言 之前對於用SelfHost來手動實現Web API的宿主模式,似乎不是太深入,所以本篇文章我們一起來討論關於利用HttpClient來訪問Web API上的資源來進行探討以及註意相關事項,希望此文對你也有收穫。 來自XML或Json Content的簡單參數 當Web API方法中接受如Str ...
  • 註:下載本文提到的完整代碼示例請訪問:How to authorization Angular 2 app with asp.net core web api 在ASP.NET Core中使用Angular2,以及與Angular2的Token base身份認證 Angular2是對Angular1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...