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>

跑起來

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

 

 

 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就可用注銷了。

主體流程

  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網頁登陸里涉及到的交給核心類,之后會重新按這里的流程走走源碼...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM