天天看點

IdentityServer4網頁(單點)登陸入門

前言

本篇說說ids中的網頁登陸以及單點登陸的大緻原理,主要是以基本跑通為目的,下一篇開始會詳細說明內建ids網頁登陸原理。 

最好先熟悉以下知識:

  • asp.net core
  • asp.net core的身份驗證和基于政策的授權
  • identityServer官方文檔過一遍

推薦蔣老師的《asp.net core 3 架構解密》

場景

你在通路一個網站登陸時,可以選擇輸入賬号密碼登陸,也可以選擇第三方登陸,如:QQ、微網誌賬号等。登陸流程我就不廢話了。假設是QQ登陸,我們這裡可以通過ids4來實作QQ伺服器來向第三方應用提供身份驗證的功能。

  1. 我們有多個MVC應用,假如是mvc1、mvc2,
  2. 希望統一由IndentityServer來做使用者管理,假如這個服務叫idsServer
  3. 使用者在登陸mvc1時自動跳轉到idsServer的登陸頁面,登陸成功後mvc1能拿到一個代表此使用者的id(一個加密的字元串)
  4. 在我們後續請求mvc1時随時可以拿到使用者的id
  5. 當請求mvc2時,由于是另一給應用,沒登陸的情況下會跳轉到idsServer去做登陸
  6. idsServer檢測到這個浏覽器之前在mvc1中做過登陸,直接傳回使用者id給mvc2

到此實作了mvc應用內建ids登陸,并實作了單點登陸。步驟5、6有點玄乎,下面會說明。ids4針對使用者來說隻是做身份驗證(登陸),也就是識别出目前使用者是誰,最終展現就是我們的應用可以拿到目前使用者的id,ids4不負責使用者的應用程式功能的授權,比如通常了解的基于角色的菜單、按鈕權限

環境搭建

按官方文檔的如下步驟可以搭建環境:

  1. https://identityserver4.readthedocs.io/en/latest/quickstarts/1_client_credentials.html
  2. 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>      

跑起來

在解決方案上右鍵->屬性

IdentityServer4網頁(單點)登陸入門

 Ctrl + F5 走起...

此時由于mvc1和2的HomeController.Index是受保護的資源,首次通路因為使用者并沒有登陸,是以會調轉到ids的登入頁去

IdentityServer4網頁(單點)登陸入門

 錄入測試賬号和密碼,ailice點選登陸,此時會跳轉到mvc1的首頁,因為已登陸成功,是以此時頁面可用正常方案

IdentityServer4網頁(單點)登陸入門

此時若去通路mvc2的首頁https://localhost:5003/你會發現它會跳轉以下,最後直接就可用通路,并不需要我們再登陸了,這就是所謂的單點登陸。

如何登出?

登出時要清楚本地登陸和ids那邊的登陸狀态,在mvc1和2的HomeController中加入如下Action

public IActionResult Logout()
{
    return SignOut("Cookies", "oidc");
}      

此時通路下這個Action就可用登出了。

主體流程

IdentityServer4網頁(單點)登陸入門
  1. 首先使用者請求mvc1的受保護頁面,mvc1的授權政策檢測使用者未登入,發出一個質詢,由ids用戶端庫提供的身份驗證處理器(在startup中配置的那個"oidc"的身份驗證方案)處理這個質詢,組織請求參數并跳重定向使用者轉到idsServer的登入頁
  2. idsServer的AccountController.Login接收請求,通過互相服務接口IIdentityServerInteractionService對目前請求做驗證(用戶端啊、請求的scope啊、等等..),驗證成功的話,得到一個結果AuthorizationRequest,表示目前授權請求,裡面包含用戶端id及其它參數
  3. 根據結果組織一個ViewModel,主要是決定是否顯示第三方登陸(用戶端請求時指定了希望哪種登陸方式?用戶端配置時指定了支援哪些驗證方式?idsServer預設支援哪些驗證方式?)
  4. 假如使用者使用賬号密碼登陸,輸入後送出
  5. AccountController.Login Post接收請求,做步驟2一樣的事,驗證下用戶端以及其它參數的驗證,若通過則驗證使用者賬号密碼,若成功則得到使用者實體(ids中注冊的使用者資訊)
  6. ids自己做本地登陸,将使用者資訊加密存儲到cookie中,然後跳轉到自己的/connect/authenraztion/callback終結點
  7. 在/callback終結點中先驗證用戶端送出的各參數,生成臨時code,回調用戶端的".../signin-oidc"
  8. 用戶端攜帶clientid 密鑰 code 之類的參數找ids請求idToken和accessToken
  9. ids傳回idToken和accessToken,mvc1服務端存儲它們,然後将使用者辨別加密存儲到使用者的cookie中
  10. 使用者後續攜帶使用者辨別cookie請求mvc1就可用了
  11. mvc1有時候需要攜帶accessToken通路被ids保護的第三方接口
  12. 當使用者發起登出調用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