本章主要內容有:
● 實現基於微軟帳戶的第三方身份驗證
● 實現雙因子身份驗證
● 驗證碼機制html
在微軟提供的ASP.NET MVC模板代碼中,默認添加了微軟、Google、twitter以及Facebook的帳戶登陸代碼(雖然被註釋了),另外針對國內的一些社交帳戶提供了相應的組件,全部組件均可以經過Nuget包管理器安裝:算法
從上圖中看到有優酷、微信、QQ、微博等組件,其中一些是微軟提供的,一些是其它開發者提供的。而本文將使用微軟帳戶爲例來介紹如何實現一個第三方登陸。
注:本章主要代碼參考ASP.NET MVC模板代碼,因此在文章中只列出關鍵代碼,其他代碼與模板中的徹底一致。數據庫
在開發以前首先須要經過Nuget安裝Microsoft.Owin.Security.MicrosoftAccount:安全
另外就是須要去微軟的開發者中心使用微軟帳戶建立一個本身的應用信息https://apps.dev.microsoft.com/,並保存應用的ID以及密鑰用於對身份驗證中間件進行配置:微信
建立過程以下:
1. 點擊添加應用按鈕,進入應用程序註冊頁面,填寫應用名稱並點擊Create按鈕(注:因爲我已經有一個名稱爲My Blog的App,因此下面的Test App的建立流程僅僅是用於演示,後續的身份驗證明際上是使用以前建立的My Blog):app
2. 在後續頁面中點擊生成新密碼來生成密鑰(注:該密碼只顯示一次,須要在彈出框中複製並保存下來):ide
3. 添加平臺:點擊添加平臺按鈕,添加一個Web平臺,並在平臺的重定向Url中填入本地調試的地址信息(注:必定須要啓動HTTPS而且地址後須要添加signin-microsoft,VS能夠在項目的屬性中開啓SSL,並設置SSL的URL):加密
4. 保存更改。3d
在上一篇文章中介紹了,第三方帳戶身份驗證除了特定帳戶身份驗證中間件外,還須要添加一個消極模式的外部Cookie身份驗證中間件,因此首先須要在項目的Startup文件中添加一下代碼:調試
而後再在該中間件後加入微軟身份驗證中間件(注:中間件順序會影響處理流程,微軟身份驗證中間件必須在外部Cookie中間件後),並設置上面建立的應用ID及密鑰:
如今能夠說應用中已經支持微軟的帳戶身份驗證了,可是在應用中還未提供微軟身份驗證的入口,以及登錄後用戶信息的補全等功能。
1. 在頁面上添加驗證入口,在Login頁面上加入如下代碼,經過AuthenticationManager來獲取全部的第三方身份驗證方式,並生成對應連接:
2. 在AccountController中添加ExternalLogin Action方法(注:該方法主要目的是調用AuthenticationManager的Challenge方法來觸發微軟身份驗證中間件的ResponseChallenge方法來完成頁面的跳轉):
其中ChallengeResult是一個自定義的ASP.NET MVC Reuslt類型:
3. 加入第三方驗證後的回調方法ExternalLoginCallback,該回調方法是獲取第三方身份驗證後的用戶信息,而後在本地數據庫中查找該用戶,若是存在那麼登陸成功,不然須要對該用戶信息進行補全。
4. 添加第三方帳戶信息補全頁面及Action方法,其中action方法接收到補全的用戶信息後完成用戶註冊功能,但要注意的是第三方帳戶沒有密碼,僅僅是在AspNetUserLogins表中添加了第三方驗證的信息:
運行結果:
1.訪問登陸頁面出現Microsoft的按鈕(注:必須使用HTTPS地址才能正常的使用微軟身份驗證):
2. 點擊微軟身份驗證按鈕後,跳轉到微軟帳戶登陸頁面:
3. 完成登陸後,因爲是第一次登陸,因此會跳轉到信息補全頁面:
輸入郵箱後將登陸成功:
數據庫中的信息:
上圖中能夠看到無密碼,而後在Login表中有一條數據:
Identity的雙因子身份驗證明際上是Identity的一個內置功能,爲何說是內置呢?由於只須要實現信息的發送(如郵件、短信等),而後再對Identity中的SignInManager進行簡單的配置而後添加一些用於發送、填寫驗證碼的頁面就能夠完成。因此首先須要完成的就是實現信息發送功能。
注:這裏信息發送功能使用將信息寫到硬盤的方式模擬。
1. 實現信息的發送:
在ASP.NET MVC默認的模板中就爲咱們建立了以下代碼:
默認的郵件及短信發送器,只不過它沒有實現,僅僅是返回了一個空值,如今使用寫硬盤的方式將信息寫到硬盤上:
2. 完成UserManager的雙因子驗證配置:
三個關鍵點:1. TokenProvider,它用來生成驗證碼。2. 信息格式。3. 信息發送服務。
3. 在身份驗證管道中加入雙因子驗證中間件:
兩個中間件前者用於處理二次驗證,後者用於記住登陸狀態,下次訪問系統時自動登陸。
4. 添加驗證碼發送方式選擇以及驗證碼填寫頁面及相應的Action方法(代碼略)。
5. 在數據庫中將演示用的用戶信息改成啓用二次驗證(注:模板代碼中有用於管理我的信息的功能,此處省略了實現,直接經過修改數據數據的方式開啓用戶的雙因子驗證、添加電話號碼等):
6. 運行結果:
登陸後須要選擇驗證碼發送方式:
選擇後點擊提交按鈕,頁面調整到驗證頁面的同時,指定的文件中生成了須要的驗證碼:
填寫驗證碼後點擊提交按鈕,則登陸成功:
注:雙因子驗證也能夠應用到第三方帳戶的登陸方式上,雙因子驗證只與用戶有關與身份驗證方式無關。
對於雙因子驗證來講,它實際上就是在普通驗證或第三方帳戶驗證的基礎上增長了驗證碼的發送和驗證兩個環節,那麼對於驗證碼這個主體Identity是如何來維護的呢?
在上面的介紹中,有一個環節就是須要經過對UserManager進行配置以支持雙因子驗證的消息發送、消息生成等等:
根據這個代碼看來XXXTokenProvider是專門用來維護驗證碼的,而XXXService是用來發送的,因此這裏將對TokenProvider進行說明,瞭解驗證碼是如何維護的:
上圖是TokenProvider相關的一個簡單類圖,從類圖中能夠看出TokenProvider其實是實現了一個名爲IUserTokenProvider的接口,該接口中有4個方法,它們的做用分別是:
● GenerateAsync:根據UserManager以及User信息來生成一個令牌(Token)。
● IsValidProviderForUserAsync:判斷這個Token提供器對這個用戶是不是有效的(若是使用短信驗證,可是該用戶沒有設置手機號,那麼就是無效的)。
● NotifyAsync:當Token生成後調用該方法通知用戶,如短信或郵件通知。
● ValidateAsync:用於驗證Token是否有效。
而TotpSecutityStampBasedTokenProvider是一個實現了IUserTokenProvider接口的,經過用戶安全戳生成驗證碼的生成器:
從代碼中能夠看到該算法是基於rfc6238(TOTP: Time-Based One-Time Password Algorithm,基於時間的一次性密碼算法) https://tools.ietf.org/html/rfc6238,而後經過用戶的安全戳以及GetUserModifierAsync方法生成特定的信息熵來完成密碼加密,關於信息熵可參考:https://www.zhihu.com/question/22178202,上面將生成後的令牌執行ToString("D6")是將其轉換爲一個6位數字的字符串。
而Token的驗證方式和生成差很少都是經過用戶安全戳和信息熵來驗證提交的驗證碼(它其實是一種hash算法):
以上已經解釋了最初驗證碼的生成和驗證的問題,因此對於EmailTokenProvider和PhoneNumberTokenProvider只是對熵的生成、對Provider的有效性(是否存在Email或電話號碼)、通知方式進行了修改,下面是PhoneNumberTokenProvider相關代碼:
本章主要是使用代碼的形式實現了ASP.NET中的第三方驗證和雙因子驗證,文中的代碼都來自ASP.NET MVC的模板,因此文中僅僅是對關鍵的代碼進行了介紹,一些細節的內容可參考完整代碼。其中第三方驗證使用的是微軟帳戶,若是有環境支持能夠嘗試國內的微信、QQ等身份驗證。
另外在文章最後對驗證碼的生成和校驗代碼進行了分析,知道了它是基於Hash算法的信息加密、驗證的機制來實現的。
ASP.NET MVC基於Identity提供了很是完善、強大的用戶管理和身份驗證功能,除了以上介紹的之外還有帳戶鎖定、註冊郵箱或短信驗證功能,基本上已經涵蓋了如今開發經常使用的功能,但這些功能被一個模板實現了,因此ASP.NET強大嗎?