前言
本篇說說ids中的網頁登陸以及單點登陸的大緻原理,主要是以基本跑通為目的,下一篇開始會詳細說明內建ids網頁登陸原理。
最好先熟悉以下知識:
- asp.net core
- asp.net core的身份驗證和基于政策的授權
- identityServer官方文檔過一遍
推薦蔣老師的《asp.net core 3 架構解密》
場景
你在通路一個網站登陸時,可以選擇輸入賬号密碼登陸,也可以選擇第三方登陸,如:QQ、微網誌賬号等。登陸流程我就不廢話了。假設是QQ登陸,我們這裡可以通過ids4來實作QQ伺服器來向第三方應用提供身份驗證的功能。
- 我們有多個MVC應用,假如是mvc1、mvc2,
- 希望統一由IndentityServer來做使用者管理,假如這個服務叫idsServer
- 使用者在登陸mvc1時自動跳轉到idsServer的登陸頁面,登陸成功後mvc1能拿到一個代表此使用者的id(一個加密的字元串)
- 在我們後續請求mvc1時随時可以拿到使用者的id
- 當請求mvc2時,由于是另一給應用,沒登陸的情況下會跳轉到idsServer去做登陸
- idsServer檢測到這個浏覽器之前在mvc1中做過登陸,直接傳回使用者id給mvc2
到此實作了mvc應用內建ids登陸,并實作了單點登陸。步驟5、6有點玄乎,下面會說明。ids4針對使用者來說隻是做身份驗證(登陸),也就是識别出目前使用者是誰,最終展現就是我們的應用可以拿到目前使用者的id,ids4不負責使用者的應用程式功能的授權,比如通常了解的基于角色的菜單、按鈕權限
環境搭建
按官方文檔的如下步驟可以搭建環境:
- https://identityserver4.readthedocs.io/en/latest/quickstarts/1_client_credentials.html
- https://identityserver4.readthedocs.io/en/latest/quickstarts/2_interactive_aspnetcore.html
我們這裡使用更直接一點的方式,使用它提供的項目模闆一步到位
1、安裝ids4的項目模闆
dotnet new -i IdentityServer4.Templates
2、根據模闆建立ids4項目
dotnet new is4inmem
此模闆建立會直接幫你建立要給立即可用的ids服務應用,裡面的用戶端、資源、使用者都是以記憶體的形式定義的。直接F5就可用跑起來
3、在ids服務端中注冊mvc1、mvc2的配置
就是在ids登記下這倆用戶端,我是ids,你倆要讓我來幫你們做登陸得先來我這裡登個記對吧
在Config.Clients中添加如下配置:
new Client
{
//用戶端id
ClientId = "mvc1",
//用戶端密鑰
ClientSecrets = { new Secret("secret".Sha256()) },
//授權模式為code
AllowedGrantTypes = GrantTypes.Code,
//ids發放code時要回調用戶端的位址
RedirectUris = { "https://localhost:5002/signin-oidc" },
//完成在ids中登出後回調用戶端的這個位址
PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
//ids允許此用戶端通路這些scope
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
mvc2的配置一樣。
4、建立mvc1、mvc2用戶端
5、配置mvc1用戶端,mvc2類似略了
5.1、調整倆項目啟動監聽的端口,防止3個項目的端口沖突,我這裡ids用的5001,mvc1用的5002,mvc2用的5003
5.2、引用nuget包
install-package Microsoft.AspNetCore.Authentication.OpenIdConnect
5.3、在startup.cs中做配置
1 public void ConfigureServices(IServiceCollection services)
2 {
3 services.AddControllersWithViews();
4 JwtSecurityTokenHandler.DefaultMapInboundClaims = false;//還沒研究過它是幹啥的
5 services.AddAuthentication(options => //注冊asp.net core 身份驗證核心服務,并配置
6 {
7 options.DefaultScheme = "Cookies";//預設的身份驗證方案名
8 options.DefaultChallengeScheme = "oidc";//用來跳轉到dis登入頁的身份驗證方案名
9 //注意這倆配置與下面注冊的身份驗證方案的名字對應
10 })
11 .AddCookie("Cookies")//注冊asp.net core 預設的基于cookie的身份驗證方案
12 .AddOpenIdConnect("oidc", options =>//注冊ids為我們提供的oidc身份驗證方案
13 {
14 options.Authority = "https://localhost:5001";//配置ids的根路徑
15 options.ClientId = "mvc1";//此客戶但的id
16 options.ClientSecret = "secret";//此用戶端的密鑰
17 options.ResponseType = "code";//授權模式
18 options.SaveTokens = true;//是否将最後擷取的idToken和accessToken存儲到預設身份驗證方案中
19 });
20 }
5.4、在startup.cs中做配置啟用asp.net core的身份驗證中間件
1 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
2 {
3 //略...
4 app.UseAuthentication();
5 app.UseAuthorization();
6 //略...
7 }
5.5、找個Controller的Action來充當受保護的頁面,比如HomeController.Index
[Authorize]
public IActionResult Index()
{
return View();
}
5.6、為了容易看到效果,可用修改下首頁的視圖,顯示下目前登陸使用者的資訊
1 @using Microsoft.AspNetCore.Authentication
2 <h2>Claims</h2>
3 <dl>
4 @foreach (var claim in User.Claims)
5 {
6 <dt>@claim.Type</dt>
7 <dd>@claim.Value</dd>
8 }
9 </dl>
10 <h2>Properties</h2>
11 <dl>
12 @foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)
13 {
14 <dt>@prop.Key</dt>
15 <dd>@prop.Value</dd>
16 }
17 </dl>
跑起來
在解決方案上右鍵->屬性
Ctrl + F5 走起...
此時由于mvc1和2的HomeController.Index是受保護的資源,首次通路因為使用者并沒有登陸,是以會調轉到ids的登入頁去
錄入測試賬号和密碼,ailice點選登陸,此時會跳轉到mvc1的首頁,因為已登陸成功,是以此時頁面可用正常方案
此時若去通路mvc2的首頁https://localhost:5003/你會發現它會跳轉以下,最後直接就可用通路,并不需要我們再登陸了,這就是所謂的單點登陸。
如何登出?
登出時要清楚本地登陸和ids那邊的登陸狀态,在mvc1和2的HomeController中加入如下Action
public IActionResult Logout()
{
return SignOut("Cookies", "oidc");
}
此時通路下這個Action就可用登出了。
主體流程
- 首先使用者請求mvc1的受保護頁面,mvc1的授權政策檢測使用者未登入,發出一個質詢,由ids用戶端庫提供的身份驗證處理器(在startup中配置的那個"oidc"的身份驗證方案)處理這個質詢,組織請求參數并跳重定向使用者轉到idsServer的登入頁
- idsServer的AccountController.Login接收請求,通過互相服務接口IIdentityServerInteractionService對目前請求做驗證(用戶端啊、請求的scope啊、等等..),驗證成功的話,得到一個結果AuthorizationRequest,表示目前授權請求,裡面包含用戶端id及其它參數
- 根據結果組織一個ViewModel,主要是決定是否顯示第三方登陸(用戶端請求時指定了希望哪種登陸方式?用戶端配置時指定了支援哪些驗證方式?idsServer預設支援哪些驗證方式?)
- 假如使用者使用賬号密碼登陸,輸入後送出
- AccountController.Login Post接收請求,做步驟2一樣的事,驗證下用戶端以及其它參數的驗證,若通過則驗證使用者賬号密碼,若成功則得到使用者實體(ids中注冊的使用者資訊)
- ids自己做本地登陸,将使用者資訊加密存儲到cookie中,然後跳轉到自己的/connect/authenraztion/callback終結點
- 在/callback終結點中先驗證用戶端送出的各參數,生成臨時code,回調用戶端的".../signin-oidc"
- 用戶端攜帶clientid 密鑰 code 之類的參數找ids請求idToken和accessToken
- ids傳回idToken和accessToken,mvc1服務端存儲它們,然後将使用者辨別加密存儲到使用者的cookie中
- 使用者後續攜帶使用者辨別cookie請求mvc1就可用了
- mvc1有時候需要攜帶accessToken通路被ids保護的第三方接口
- 當使用者發起登出調用Home/logout時,在mvc1中注冊的兩個身份驗證方案都會執行,"Cookies"将情況使用者本地儲存使用者辨別的cookie,“oidc”會與ids通信,删除ids存到使用者浏覽器中的cookie,此時ids還會以某種機智通知到其它已登陸的用戶端,如何通知的後面再說
單點登陸的重點
按流程看,使用者浏覽器存儲了兩份代表使用者辨別的cookie,一個在idsServer域名下,要給在mvc1域名下,當mvc跳轉到ids登入頁時,會攜帶ids域名下的cookie
ids一看,這使用者登陸過,就直接攜帶使用者資訊和token并跳轉到回調用戶端的".../signin-oidc",用戶端的後續步驟不變
結尾
本篇隻是草草說了各大概,下一篇會先說說ids網頁登陸裡涉及到的交給核心類,之後會重新按這裡的流程走走源碼...
用支付寶掃一掃,咱倆都可以獲得一個小紅包
關注我的今日頭條,有不錯的c#.net經驗分享
本文來自部落格園,作者:變形精怪,轉載請注明原文連結:https://www.cnblogs.com/jionsoft/p/13545273.html