Identity Server4 基礎應用(一)

来源:https://www.cnblogs.com/xhy0826/archive/2020/03/14/12489772.html
-Advertisement-
Play Games

前言 Identity Server4基於OAuth2.0協議的一套用於身份認證和授權的框架。OAuth2.0協議是一個委托協議,通過這個協議,我們可以讓某個客戶端頂著一個有資源訪問許可權的身份去訪問那些被保護的資源。授權的流程簡單概括起來,客戶端應用需要先去請求Identity Server4,如果 ...


前言

  Identity Server4基於OAuth2.0協議的一套用於身份認證和授權的框架。OAuth2.0協議是一個委托協議,通過這個協議,我們可以讓某個客戶端頂著一個有資源訪問許可權的身份去訪問那些被保護的資源。授權的流程簡單概括起來,客戶端應用需要先去請求Identity Server4,如果Identity Server4覺得你的身份符合就會給你一個Access Token,之後這些客戶端再帶著這個Access Token去訪問受保護的資源(例如說一個Asp.Net Core WebApi),就能夠得到想要的Response了。下麵兩張是來自官方的示意圖。

    

  原理概括起來是這樣,但是由於存在著多種多樣的客戶端程式(ASP.Net Core MVC,WPF,Angular等),需要針對不同的類型選擇不同的授權方式(Grant Types, 也常稱flows或者protocol flows)來完成授權,接下來我們從易到難的依次學習不同的授權流程,以下篇幅是基於.NET Core 3.1與IdentityServer4 V3.1.0.0版本開發。

準備工作

  • 為本地安裝Identity Server4框架的模板在cmd中執行“dotnet new -i identityServer4.Templates"安裝Identity Server4的應用模板。執行完之後可調用“dotnet new --help”看到我們的vs多出6個模板,如下圖

  • 接著我們需要選擇一種模板來創建項目,簡單起見,我們先選擇了In-Memory Stores and Test User這個方式,因為這個從名字看就知道是提供給學習者入門用的,算是簡單的一種了,接著cd到一個存放項目的路徑下後,接著執行: dotnet new is4inmem --name Is4Test1,這樣就能創建一個Identity Server4的項目了,這就是template的便捷。
  • 接下來補充一點理論上的東西,我們前面提到根據不同的情況,我們會選擇不同的授權方法,在OAuth2.0上授權類型分為下圖(官網上的圖)這幾種,今天我們從 “Client Credentials 客戶端憑證”的授權方式入手,先從這個開始學習也是因為這是最簡單的一種方式,這種方式常用於沒有具體用戶(人)的情況下,用官文的話說就是Machine to Machine Communication。

  • 簡單的概述下Client Credentials Flow。在Client Credentials Flow下,往往是一個程式或者是伺服器直接與授權伺服器進行授權申請,而申請只需要提供ClientID和Client secret去授權伺服器的Token終結點,如果認證通過,授權伺服器則會返回“Access Token”這個令牌給客戶端程式,客戶端程式隨後存下這個令牌,再去訪問授權伺服器保護的資源時,只要攜帶這個令牌,則可以訪問到需要訪問的資源了。接下來我們再從代碼中邊做實驗邊學習。

配置Identity Server4

  首先我們打開Identity Server4項目,就是剛剛利用模板創建的項目“Is4Test1”,由於我們選擇的模板是將身份認證的數據存在記憶體中的,在Startup.cs中,可以看到在ConfigureServices方法中利用靜態類進行了必要數據的填充。

1 builder.AddInMemoryIdentityResources(Config.Ids); 
2 builder.AddInMemoryApiResources(Config.Apis); 
3 builder.AddInMemoryClients(Config.Clients);

  從Config類導航進去可以看到相關的信息,在Client Credentials授權方式下,我們需要在授權伺服器上定義兩樣東西

  1.  API資源,可以看成我們需要保護資源的門牌號吧。

    1 public static IEnumerable<ApiResource> Apis =>
    2     new ApiResource[]
    3     {
    4         new ApiResource("api1", "WebApi #1"),
    5         new ApiResource("api2", "MVC #2"),
    6     };
  2. Client客戶端,這裡並非是定義我們的客戶端程式,看成客戶端程式訪問授權伺服器時,用以身份驗證的Client,其中包括為幾個屬性賦值

     1 public static IEnumerable<Client> Clients =>
     2     new Client[]
     3     {
     4         new Client
     5         {
     6             ClientId = "client1",   //看成“申請授權的客戶端程式”的賬號
     7             ClientName = "Client Credentials Client",    //看成只是對這個Client的描述信息
     8             AllowedGrantTypes = GrantTypes.ClientCredentials,   //枚舉類型,指明我們的授權方式是:Client Credentials
     9             ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },    //可以看成“申請授權的客戶端程式”的密碼
    10             AllowedScopes = { "api1" }     //這個客戶端可以訪問“api1”這個門牌號里對應的資源
    11         }
    12     };

  接著,需要在Startup的ConfigureService中添加對IdentityServer4的服務註冊

 1 //在這裡註冊Identity Server4
 2 var builder = services.AddIdentityServer(options =>
 3 {
 4     options.Events.RaiseErrorEvents = true;
 5     options.Events.RaiseInformationEvents = true;
 6     options.Events.RaiseFailureEvents = true;
 7     options.Events.RaiseSuccessEvents = true;
 8 });
 9 
10 // 將數據保存在記憶體中
11 builder.AddInMemoryIdentityResources(Config.Ids);    //用戶的身份信息,也是受保護資源的一部分(Identity Data)
12                                                      //由於當前使用Client Credentials方式沒有具體的用戶,所以這部分資源暫時用不上
13 builder.AddInMemoryApiResources(Config.Apis);        //受保護的資源(Apis)
14 builder.AddInMemoryClients(Config.Clients);          //授權的用戶模式
15 builder.AddTestUsers(TestUsers.Users);               //增加了測試用戶

  到此,可以使用Client Credential的授權伺服器就已經配置完畢了。接下來直接運行就會跳轉到5000埠的預設頁面(如果沒有改配置中的埠的話預設是5000),這個時候訪問“http://localhost:5000/.well-known/openid-configuration”或者點擊頁面上的“discovery document”鏈接便可跳轉到Identity Server4的“發現文檔(discovery Doc)”可以看到授權伺服器的很多終結點(EndPoint)信息和描述信息,這些終結點是後面客戶端程式訪問授權伺服器需要用到的。如下圖可見。

 

創建要添加保護的Api資源

  當Identity Server4運行起來後就可以創建一個我們想保護的Api資源。我們創建一個ASP.NET Core WebApi項目,配置埠為5001(自便,不要和授權伺服器的5000埠衝突就好),隨後創建一個Controller命名為“IdentityController”。

 1 namespace API1.Controllers
 2 {
 3     [Route("identity")]
 4     [Authorize]
 5     public class IdentityController : ControllerBase
 6     {
 7         [HttpGet]
 8         public IActionResult Get()
 9         {
10             return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
11         }
12     }
13 }

  接著來到Startup中來註冊服務和配置中間件,在這之前我們需要通過Nuget添加一個“Microsoft.AspNetCore.Authentication.JwtBearer”的引用,Jwt就是JSON Web Token的縮寫,是一種流行的跨域認證解決方案。而Bearer是OAuth中的一種認證類型。

 1 public class Startup
 2 {
 3     public void ConfigureServices(IServiceCollection services)
 4     {
 5         services.AddControllers();
 6         services.AddAuthentication("Bearer")
 7             .AddJwtBearer("Bearer", options =>
 8             {
 9                 options.Authority = "http://localhost:5000";  //這裡指定授權伺服器的地址
10                 options.RequireHttpsMetadata = false;       //暫時先不用https
11                 options.Audience = "api1";                  //關聯到授權伺服器上的api資源,住進“api1”這個門牌號里
12             });
13     }
14 
15     public void Configure(IApplicationBuilder app)
16     {
17         app.UseRouting();
18         app.UseAuthentication();    //添加身份認證的中間件
19         app.UseAuthorization();     //添加授權中間件,是我們api的終結點被訪問時需要經過授權,從而拒絕匿名訪問
20         app.UseEndpoints(endpoints =>
21         {
22             endpoints.MapControllers()
23                 .RequireAuthorization();
24             //在這裡配置RequireAuthorization()的話整個網站應用都會要進行授權驗證,
25             //我們也可通過在Controller上應用[Authorize]特性來達到同樣的效果
26         });
27     }
28 
29 }

創建客戶端來訪問受保護的API

  新建一個Console控制台應用程式,並通過Nuget添加“IdentityModel”引用。隨後我們便可以像下麵一樣進行實驗。

 1 static async Task Main(string[] args)
 2 {
 3     //**********【Step1】 獲取Identity Server4的終結點信息**************
 4     var client = new HttpClient();
 5     var disco = await client.GetDiscoveryDocumentAsync(); //調用這個方法獲取Identity Server4的信息
 6     if (disco.IsError)
 7     {
 8         Console.WriteLine(disco.Error);
 9     }
10 
11     //**********【Step2】 請求Access Token**********
12     var tokenReponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
13     {
14         Address = disco.TokenEndpoint,
15         ClientId = "client1",      //類比成這個客戶端應用的賬戶
16         ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",  //類比成這個客戶端應用的密碼
17         Scope = "api1"             //指定授權範圍
18     });
19     if (tokenReponse.IsError)
20     {
21         Console.WriteLine(tokenReponse.Error);
22     }
23 
24     //**********【Step3】 如果上面正常運行下來,就獲得了Access Token了,那麼接下來要使用Access Token來訪問我們受保護的資源
25     var apiClient = new HttpClient();
26     apiClient.SetBearerToken(tokenReponse.AccessToken); //將獲得的Access Token放到Header中再去請求資源
27     var response = await client.GetAsync("http://localhost:5001/identity");  //訪問受保護資源
28     if (!response.IsSuccessStatusCode)    //如果訪問失敗
29     {
30         Console.WriteLine(response.StatusCode);
31     }
32     else   //訪問成功,將結果輸出到控制台
33     {
34         var content = await response.Content.ReadAsStringAsync();
35         Console.WriteLine(JArray.Parse(content));
36     }
37     Console.ReadLine(); 
38 }

  啟動Api程式和Console程式,運行起來後我們可以在控制臺上看到從Api上獲取到的信息,你也可以直接在瀏覽器中去直接請求Api的identity資源,應該會得到一個401的錯誤消息代表用戶沒有許可權。

  接著我們用抓包工具來驗證一下,我們抓取在訪問資源時的請求,在請求的Header中看到確實存在Access Token。

  現在我們再回過頭來整理一遍Client Credentials的認證流程,我繪製了下麵的一個簡圖

  

參考資料:

官文:https://identityserver4.readthedocs.io/en/latest/quickstarts/1_client_credentials.html

楊旭大佬:https://www.cnblogs.com/cgzl/p/9221488.html

大佬的視頻教程:https://www.bilibili.com/video/av42364337

 


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

-Advertisement-
Play Games
更多相關文章
  • 本人免費整理了Java高級資料,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高併發分散式等教程,一共30G,需要自己領取。傳送門:https://mp.weixin.qq.com/s/osB-BOl6W-ZLTSttTkqMPQ 第 ...
  • 省市遞歸載入到TreeView只是遞歸的一個表現方式,使用遞歸可以達到很多的功能,類似我們電腦本地的 磁碟目錄文件載入等等均是該原理,十分便捷。 後續還會附上目錄載入、以及添加、刪除、修改父子節點等等 ...
  • 《框架設計 CLR Via C#》 (第2版) [作者] (美) Jeffrey Richter[譯者] (中) 周靖 張傑良[出版] 清華大學出版社[版次] 2006年11月 第1版[印次] 2007年02月 第2次 印刷[定價] 68.00元 【前言】 Microsoft .NET Framew ...
  • 一個非常輕量級的 Web API Demo,代碼量很少,實現了方法攔截器,token校驗,異常攔截器,緩存 創建項目:如果選擇Web API,項目中東西會比較多,這裡選擇Empty,把下麵的Web API勾上,MVC不要勾 項目目錄結構: Global.asax.cs代碼:這裡配置方法攔截器和異常攔 ...
  • ASP.NET WebAPI有兩種寄宿模式,一種是WebHost,一種是SelfHost,為什麼可以有兩種模式的原因在於WebAPI有一個相對獨立的消息處理管道,只要給這個消息管道傳遞一個封裝好的對象,便可以得到處理好的結果。而怎麼去封裝這個對象,如何得到這個對象就不是WebAPI所關心的了。在We... ...
  • 記錄什麼是托管代碼?學習過程。 托管代碼 C#,就是其中一種托管代碼。托管代碼的執行過程可以交由運行時管理,在.Net里,這種運行時稱為“公共語言運行時”(Common Language RunTime,CLR)。 托管代碼先經過編譯器編譯成“中間語言”代碼(Intermediate Languag ...
  • 我就直奔主題了。 我按照大的方向總結了一下: 學習習慣 按照自己的生活習慣,每天或者每周給自己安排學習時間,如果執行一段時間不能堅持,學習時間減半方法繼續執行。 註意:比學習更重要的是學習習慣。習慣練成了已經成功一半了。 學習方法 學習途徑有很多種,常用的有看書,看視頻,去培訓班,老師輔導。 怎樣提 ...
  • 我們可以在Github上面直接查看ASP.NET Core 3.x的源代碼,但是我們也可以把源代碼下載下來進行查看。 而下載源代碼進行查看有很多好處: 任意的導航源代碼 內置了一個示例項目 直接調試源代碼 下載源代碼 想下載並配置好源碼,你需要: 最新版的Visual Studio 或者其它IDE ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...