asp.net core系列 54 IS4用客戶端憑據保護API

来源:https://www.cnblogs.com/MrHSR/archive/2019/04/12/10688707.html
-Advertisement-
Play Games

一. 概述 本篇開始進入IS4實戰學習,從第一個示例開始,該示例是 “使用客戶端憑據保護API”,這是使用IdentityServer保護api的最基本場景。該示例涉及到三個項目包括:IdentityServer項目、API項目、Client項目,都有自己的宿主,為了方便開發,放在了一個解決方案下( ...


一. 概述

  本篇開始進入IS4實戰學習,從第一個示例開始,該示例是 “使用客戶端憑據保護API”,這是使用IdentityServer保護api的最基本場景。該示例涉及到三個項目包括:IdentityServer項目、API項目、Client項目,都有自己的宿主,為了方便開發,放在了一個解決方案下(Quickstart.sln),三個項目的分工如下:

         (1) IdentityServer項目是包含基本的IdentityServer設置的ASP.NET Core應用程式,是令牌端點。

         (2) API項目是Web Api,是要保護的資源。

         (3) Client項目是客戶端用戶,用來訪問Web Api。

  最後客戶端Client項目請求獲取IdentityServer上的訪問令牌。作為客戶端Client和IdentityServer都知道secret密鑰,Client將使用令牌訪問Web API。開源地址Github

 

二. 創建IdentityServer項目 

  創建一個ASP.NET Core Web(或空)模板。項目名為IdentityServer,解決方案為Quickstart。是一個包含基本IdentityServer設置的ASP.NET Core應用程式。該項目使用的協議是http,當在Kestrel上運行時,埠設置為5000或在IISExpress上的隨機埠。

  首次啟動時,IdentityServer將為您創建一個開發人員簽名密鑰,它是一個名為的文件tempkey.rsa。您不必將該文件檢入源代碼管理中,如果該文件不存在,將重新創建該文件。項目最終目錄結構如下所示:

  下麵進行說明,以及用序號來表示開發實現步驟:

  2.1 安裝:Install-Package IdentityServer4

  2.2 新增Config.cs文件, 該文件是IdentityServer資源和客戶端配置文件。在該文件中定義API資源,以及定義客戶端(可以訪問此API的客戶端)

        /// <summary>
        /// 定義API資源,要保護的資源
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<ApiResource> GetApis()
        {
            return new List<ApiResource>
            {
                new ApiResource("api1", "My API")
            };
        }
        /// <summary>
        /// 定義客戶端,可以訪問此API的客戶端
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    ClientId = "client",

                    // no interactive user, use the clientid/secret for authentication
                    AllowedGrantTypes = GrantTypes.ClientCredentials,

                    //使用密鑰進行身份認證  secret for authentication
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },

                    //客戶端允許訪問的範圍
                    AllowedScopes = { "api1" }
                }
            };
        }

  2.3 Startup配置    

        /// <summary>
        /// 配置IdentityServer,載入API資源和客戶端
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            // uncomment, if you wan to add an MVC-based UI
            //services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
             //添加AddIdentityServer
            var builder = services.AddIdentityServer()
                //添加記憶體的Identity資源
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                //添加api資源
                .AddInMemoryApiResources(Config.GetApis())
                 //添加clinet
                .AddInMemoryClients(Config.GetClients());

            if (Environment.IsDevelopment())
            {
          //開發環境下使用臨時簽名憑據 builder.AddDeveloperSigningCredential(); }
else { throw new Exception("need to configure key material"); } }
        public void Configure(IApplicationBuilder app)
        {
            if (Environment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            // uncomment if you want to support static files
            //app.UseStaticFiles();

            app.UseIdentityServer();

            // uncomment, if you wan to add an MVC-based UI
            //app.UseMvcWithDefaultRoute();
        }

  運行伺服器並瀏覽瀏覽器 http://localhost:5000/.well-known/openid-configuration, 客戶端和API將使用它來下載必要的配置數據。下麵是截取的部分配置數據:

 

三. 創建API項目

  在解決方案下繼續添加API項目,添加ASP.NET Core Web API(或空)模板。將API應用程式配置為http://localhost:5001運行。項目最終目錄結構如下所示:

  (1) 在API項目中添加一個新文件夾Controllers和一個新控制器IdentityController

   //定義路由
    [Route("identity")]
    //需要授權
    [Authorize]
    public class IdentityController : ControllerBase
    {
        /// <summary>
        /// 測試授權,獲取該用戶下聲明集合Claims
        /// </summary>
        /// <returns></returns>
        public IActionResult Get()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
    }

  (2) Startup配置

    public void ConfigureServices(IServiceCollection services)
        {
            //將最基本的MVC服務添加到服務集合中
            services.AddMvcCore()
                //向基本的MVC服務中添加授權
                .AddAuthorization()
                //向基本的MVC服務中添加格式化
                .AddJsonFormatters();

            //將身份驗證服務添加到DI服務集合中,並配置"Bearer"為預設方案  
            services.AddAuthentication("Bearer")
                //驗證令牌是否有效用於此API
                .AddJwtBearer("Bearer", options =>
                {
                    options.Authority = "http://localhost:5000";
                    //在開發環境禁用,預設true
                    options.RequireHttpsMetadata = false;
                    options.Audience = "api1";
                });
        }
        public void Configure(IApplicationBuilder app)
        {
            //添加身份驗證中間件
            app.UseAuthentication();
            app.UseMvc();
        }

    啟動程式運行http://localhost:5001/identity時返回401狀態碼,未授權。意味著API需要憑證,現在受IdentityServer保護。如下所示:

 

四.創建Client項目

  我們通過上面知道,直接用瀏覽器來訪問API是返回401狀態碼未授權,下麵在Client項目中使用憑證,來獲得api授權訪問。下麵是Client項目目錄結構,這裡Client是一個控制台應用程式。對於客戶端可以是任意應用程式,比如手機端,web端,win服務等等。

  在IdentityServer的令牌端點實現了OAuth 2.0協議,客戶端可以使用原始HTTP來訪問它。但是,我們有一個名為IdentityModel的客戶端庫,它將協議交互封裝在易於使用的API中。

  3.1  安裝:Install-Package IdentityModel

  3.2  發現IdentityServer端點

    IdentityModel包括用於發現端點的客戶端庫。只需要知道IdentityServer的基地址 - 可以從元數據中讀取實際的端點地址:

        private static async Task Main()
        {
            // discover endpoints from metadata
            var client = new HttpClient();
            var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
            if (disco.IsError)
            {
                //當停掉IdentityServer服務時
                //Error connecting to http://localhost:5000/.well-known/openid-configuration: 由於目標電腦積極拒絕,無法連接。
                Console.WriteLine(disco.Error);
                return;
            }
            //...

    其中GetDiscoveryDocumentAsync是屬於IdentityModel庫的,是對HttpClient擴展方法。http://localhost:5000是IdentityServer的基地址。

  3.3  請求令牌Token

    在Mian方法中繼續向IdentityServer請求令牌,訪問api1資源。這裡的RequestClientCredentialsTokenAsync方法也是HttpClient擴展方法。

            // request token,帶入需要的4個參數,請求令牌,返回TokenResponse
            var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                //IdentityServer基地址 http://localhost:5000/connect/token
                Address = disco.TokenEndpoint,
                //設置客戶端標識
                ClientId = "client",
                //設置密鑰
                ClientSecret = "secret",
                //訪問的資源範圍
                Scope = "api1"
            });
            
            if (tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
                return;
            }
            //列印 token 信息
            Console.WriteLine(tokenResponse.Json);
            Console.WriteLine("\n\n");

  3.4 調用API

    在Mian方法中繼續向下,當訪問令牌取得後,開始調用Web API。 下麵將訪問令牌發送到Web API,通常使用HTTP Authorization標頭。這是使用SetBearerToken擴展方法完成的,該方法是IdentityModel庫的HttpClient擴展方法。

            // call api
            var apiClient = new HttpClient();
            //發送訪問令牌
            apiClient.SetBearerToken(tokenResponse.AccessToken);

            //訪問API,獲取該用戶下聲明集合Claims
            var response = await apiClient.GetAsync("http://localhost:5001/identity");
            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine(response.StatusCode);
            }
            else
            {
                //輸出 claims 名稱值 對
                var content = await response.Content.ReadAsStringAsync();
                Console.WriteLine(JArray.Parse(content));
            }

    下麵開始測試,先啟動IdentityServer程式,再啟動API程式,最後啟動Client客戶端來訪問API,通過下圖可以瞭解到:(1)客戶端請求令牌成功,(2) 客戶端使用令牌來訪問API成功。

       如果想進一步嘗試激發錯誤,來瞭解系統的行為,可以錯誤的去配置如下:

    (1) 嘗試停掉IdentityServer服務程式,這個已經測試了。

    (2) 嘗試使用無效的客戶端ID標識  ClientId = "client",

    (3) 嘗試在令牌請求期間請求無效範圍 Scope = "api1"

    (4) 嘗試在API程式未運行時調用API

    (5) 嘗試不要將令牌發送到API

  

  總結:通過本篇瞭解到了IS4保護api的最基本場景。流程是首先創建一個IdentityServer 令牌程式。 接著創建API項目,使用IdentityServer令牌程式來保護API。 最後創建要訪問的Client項目,獲取訪問令牌後再調用API方法。

    IdentityServer令牌端對要保護API資源做了配置 new ApiResource("api1", "My API")

    限制了訪問Api的客戶端標識和訪問資源範圍ClientId = "client", AllowedScopes = { "api1" }還有客戶端需要的秘鑰。

 

  參考文獻

    使用客戶端憑據保護API

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、前言 在IC前端設計/驗證領域,只會HDL遠遠不夠。目前大多數項目使用已開發好的系統架構和IP Core,因此設計部分的工作量慢慢向系統集成和驗證方向轉移。而在集成和驗證過程中,往往以各種腳本和麵向對象的高級語言為主要工具。SystemVerilog已成為主流驗證語言,相當於VerilogHDL ...
  • 現在需要做一個分散式課程設計(簡單小游戲),三個人小組合作完成。 我需要設計一個登錄註冊伺服器,接收來自網關伺服器(消息中間件)的用戶登錄註冊消息請求,然後生成訪問資料庫伺服器的消息,發送給資料庫伺服器,接收並處理其返回信息,發送登錄註冊結果給網關伺服器。(很簡單的功能) 我的想法是:登錄註冊伺服器 ...
  • 概述 什麼是線程池? 線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然後在創建線程後自動啟動這些任務。 為什麼要用線程池? 降低資源消耗 通過重覆利用已創建的線程降低線程創建和銷毀造成的消耗。 提高響應速度 當任務到達時,任務可以不需要等到線程創建就能立即執行。 提高線程的可管理性 線程是 ...
  • 結果: Loop 1Loop 2Loop 3Loop 4Loop 5Loop 6迴圈執行完啦 out of while loop Loop 1Loop 2 out of while loop 結論:while迴圈正常執行完不會執行else裡邊的代碼,如果while迴圈被break中斷則會執行else ...
  • 今天給大家帶來一篇如何評價模型的好壞以及模型的得分 最下麵的代碼最有用 一、錯誤率與精度(accuracy 準確) 錯誤率和精度是分類任務中最常用的兩種性能度量,既適用於二分類任務,也適用於多分類任務。錯誤率是分類錯誤的樣本數占樣本總數的比例,精度則是分類正確的樣本數占樣本總數的比例。 from s ...
  • 上一篇講到方法的調用和簡單的構造方法,今天繼續加深,加參數或者該參數; package sklx; public class Car{ //設三個屬性 private String 品牌; private int 價格; private String 顏色; //修改屬性參數方法 public Ca ...
  • 我們面試中經常會被問到多線程相關知識,這一塊內容往淺了說大家都會,但是一問到底層實現原理,我們往往就一臉懵逼。 這段時間準備好好學習多線程,接下來會寫一系列關於多線程的知識。 我們首先要瞭解線程,百度百科這麼介紹:線程(thread)是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中 ...
  • 思路 **先考慮一條鏈的情況怎麼做。** 因為只有兩個子樹,並且兩個子樹都是鏈。所以可以把這兩條鏈找出來,然後$sort$一下。合併起來。 **然後推廣到樹上** 對於每一棵樹都可以按照和上面同樣的方法合併成一條鏈。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...