從Client應用場景介紹IdentityServer4(二)

来源:https://www.cnblogs.com/FireworksEasyCool/archive/2018/12/18/10137011.html
-Advertisement-
Play Games

本節介紹Client的ClientCredentials客戶端模式,先看下畫的草圖: 一、在Server上添加動態新增Client的API 介面。 為了方便測試,在Server服務端中先添加swagger,添加流程可參考:https://www.cnblogs.com/suxinlcq/p/6757 ...


本節介紹Client的ClientCredentials客戶端模式,先看下畫的草圖:

一、在Server上添加動態新增Client的API 介面。

為了方便測試,在Server服務端中先添加swagger,添加流程可參考:https://www.cnblogs.com/suxinlcq/p/6757556.html

 

在ValuesController控制器中註入ConfigurationDbContext上下文,此上下文可用來載入或配置IdentityServer4.EntityFramework的Client、身份信息、API資源信息或CORS數據等。

在ValuesController中實添加以下代碼:

        private ConfigurationDbContext _context;
        public ValuesController(ConfigurationDbContext context)
        {
            _context = context;
        }

添加動態新增Client的API介面:

        [HttpPost]
        public IActionResult Post([FromBody] IdentityServer4.EntityFramework.Entities.Client client)
        {
            var res = _context.Clients.Add(client);
            if(_context.SaveChanges() >0)
                return Ok(true);
            else
                return Ok(false);
        }

控制器代碼如下:


 

二、對Server上的API進行保護

(1)安裝IdentityServer4.AccessTokenValidation包

(2)在startup.cs中ConfigureServices方法添加如下代碼:

            //protect API
            services.AddMvcCore()
            .AddAuthorization()
            .AddJsonFormatters();

            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;

                    options.ApiName = "api1";
                });

AddAuthentication把Bearer配置成預設模式,將身份認證服務添加到DI中。

AddIdentityServerAuthentication把IdentityServer的access token添加到DI中,供身份認證服務使用。

(3)在startup.cs中Configure方法添加如下代碼:

      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //if (env.IsDevelopment())
            //{
            //    app.UseDeveloperExceptionPage();
            //}

            //AddSwagger
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server介面文檔");
            });

            InitializeDatabase(app);
            app.UseAuthentication();
            app.UseIdentityServer();
            app.UseMvc();
        }

UseAuthentication將身份驗證中間件添加到管道中,以便在每次調用主機時自動執行身份驗證。

(4)在ValuesController控制器中添加[Authorize]

 

(5)在項目屬性->調試 中,啟動瀏覽器,並設成swagger,如圖:

(6)啟動項目,並調用第一個Get介面。

顯示Unauthorized(未授權),證明[Authorize]起作用了。


 

三、搭建Client客戶端

(1)新建一個控制台程式,安裝IdentityModel包

(2)添加類IDSHelper.cs,添加客戶端請求API介面代碼。

public class IDSHelper
    {
        public static async Task MainAsync()
        {
            try
            {
                DiscoveryResponse disco = await DiscoveryClient.GetAsync("http://localhost:5000");
                if (disco.IsError)
                {
                    Console.WriteLine(disco.Error);
                    return;
                }

                TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "Client", "secret");
                var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");

                if (tokenResponse.IsError)
                {
                    Console.WriteLine(tokenResponse.Error);
                    return;
                }
                Console.WriteLine(tokenResponse.Json);
                var client = new HttpClient();
                client.SetBearerToken(tokenResponse.AccessToken);
                var response = await client.GetAsync("http://localhost:5000/api/values/");
                if (!response.IsSuccessStatusCode)
                {
                    Console.WriteLine(response.StatusCode);
                }
                else
                {
                    var content = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(content);
                }
            }
            catch (Exception ex)
            {

            }
        }
}

(3)修改Program.cs代碼,如下:

class Program
    {
        static void Main(string[] args)
       => IDSHelper.MainAsync().GetAwaiter().GetResult();
    }

(4)按Ctrl+F5,可以獲取到access token和介面返回值

複製token,用postman調用,成功獲取到了介面返回值。


 

四、測試動態新增Client介面

安裝IdentityServer4包。

安裝IdentityServer4.EntityFramework包。

在IDSHelper.cs類中添加Post方法:

public static async Task Post()
        {
            try
            {
                DiscoveryResponse disco = await DiscoveryClient.GetAsync("http://localhost:5000");
                if (disco.IsError)
                {
                    Console.WriteLine(disco.Error);
                    return;
                }

                TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "Client", "secret");
                var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");

                if (tokenResponse.IsError)
                {
                    Console.WriteLine(tokenResponse.Error);
                    return;
                }
                Console.WriteLine(tokenResponse.Json);
                var client = new HttpClient();
                client.SetBearerToken(tokenResponse.AccessToken);

                Client c1 = new Client
                {
                    ClientId = "Test",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "api1" }
                };
                string strJson = JsonConvert.SerializeObject(c1 .ToEntity());
                HttpContent content = new StringContent(strJson);
                content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                //由HttpClient發出Post請求
                Task<HttpResponseMessage> response = client.PostAsync("http://localhost:5000/api/values/", content);

                if (response.Result.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    Console.WriteLine(response.Result.StatusCode);
                }
                else
                {
                    Console.WriteLine(response.Result.Content.ReadAsStringAsync().Result);
                }
            }
            catch (Exception ex)
            {

            }
        }

順便把main中改成對Post調用:

static void Main(string[] args)

       => IDSHelper.Post().GetAwaiter().GetResult();

按Ctrl+F5,調用新增Client的介面,併成功返回true。

同時可以在資料庫中的Client表找到相關記錄。需要註意的是,不能添加相同Client ID的Client。


 

五、在Client中添加Claim信息,併在API介面中對Claim信息進行驗證。

關於Claim的介紹可以看這篇文章:http://www.cnblogs.com/stulzq/p/8726002.html

這裡把Claim簡單當做用戶的身份信息使用,修改Post方法裡面的Client:

                Client c1 = new Client
                {
                    ClientId = "superAdmin",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "api1" },
                    Claims = new List<Claim>
                    {
                        new Claim(JwtClaimTypes.Role, "admin")
                    }
                };

可以看出,Claims為List,可以是很多個角色,這裡只添加一個。

Ctrl+F5,運行成功添加superAdmin Client。

 

現在,需要對Server服務端的新增Client介面進行Claim身份驗證,添加如下代碼:

   [Authorize(Roles ="admin")]

然後再客戶端修改授權的賬號為superadmin。

TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "superAdmin", "secret");

Ctrl+F5運行

問題出現了,返回了Forbidden,沒有許可權進行訪問。

這時候我們上官網查閱了資料,發現在添加Client的Claim時候,IdentityServer EntityFramework會為Claim的role添加一個預設首碼,為client_。所以,實際上它為client_role

而服務端只能對role進行驗證。

此時我們需要把Claim的預設首碼去掉,設置為空ClientClaimsPrefix = ""

 

去掉Server的Role驗證,添加形如下麵代碼的Client。

Client c1 = new Client
                {
                    ClientId = "adminClient",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "api1" },
                    Claims = new List<Claim>
                    {
                        new Claim(JwtClaimTypes.Role, "admin")
                    },
                    ClientClaimsPrefix = "" //把client_ 首碼去掉
                };

 Ctrl+F5,運行成功添加adminClient Client,這次的是Role為admin。

然後重新再Server服務端加上[Authorize(Roles ="admin")]

同時修改驗證賬號為adminClient。

TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "adminClient", "secret");

最後運行程式,成功地在[Authorize(Roles ="admin")]許可權下訪問並新增了Client。


 

六、需要註意的問題

(1)新增Client到資料庫時候,這裡需要接收IdentityServer4.EntityFramework.Entities.Client

而不是IdentityServer4.Models.Client,否則API介面在接收和轉化Client模型的時候會報錯。

(2)此外,本節介紹的Client的AllowedGrantTypes 都為 GrantTypes.ClientCredentials,相應的,客戶端請求是,需要用RequestClientCredentialsAsync方法。

最後再次提下,ClientCredentials模式的適用場景:用於和用戶無關,服務與服務之間直接交互訪問資源


 

Server服務端源碼地址:https://github.com/Bingjian-Zhu/Server

Client客戶端源碼地址:https://github.com/Bingjian-Zhu/Client

文中如有錯漏,歡迎指正。


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

-Advertisement-
Play Games
更多相關文章
  • 一、前言 準備寫這個系列文章的設想開始於今年9月,毫無意外,期間又又又又拖了很長時間,文章主要是為了記錄自己學習使用 ASP.NET Core Web API 與 Vue 創建一個前後端分離的項目的整個過程。嗯,2018年快要結束了,應該能在 .NET Core 3.0 正式版和 Vue 3.0 正 ...
  • 引用網址:http://support.microsoft.com/kb/182569/zh-cnInternet Explorer 安全區域設置存儲在以下註冊表子項下麵: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\In ...
  • Cenots7下安裝運行.NET Core、MicroSoft SQL Server 2019 preview 的基礎實踐 ...
  • 在Startup的ConfigureServices方法中加入需要依賴註入的東西。 每次從容器 中獲取的時候都是一個新的實例:services.AddTransient<ITransient, Transient>(); 每次從同一個容器中獲取的實例是相同的(一個請求內時同一個實例):service ...
  • .NET Core 可以以以下方式作為宿主運行: IIS 控制台 Windows服務 運行啟動代碼: public static void Main(string[] args) { try { LogCenter.Info("系統啟動"); LoadConfig(); bool isService ...
  • Application Services Application Services are used to expose domain logic to the presentation layer. An Application Service is called from the present ...
  • 最近在做項目中要求能夠要求動態添加資料庫並建表。具體思路如下 1 提供數據名,根據資料庫創建資料庫 2 自定資料庫與數據表,提供數據表自定與數據類型創建表 創建sqlhelper類,用於資料庫操作 編寫調用函數 最後調用 ...
  • 這是我之前寫代碼的時候被卡住的一些小知識點,看到這篇博客的人,如果有用,我很高興很夠幫助到你,如果對你沒有幫助,那麼請你路過就好 1.Winform窗體跳轉 Show(非模態顯示) 可以操作其他窗體,在彈出視窗和調用視窗之間隨意切換,比如:彈出Form2窗體了,還是原本的Form窗體進行操作 Sho ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...