內容:本文帶大家使用IdentityServer4進行對API授權保護的基本策略
作者:zara(張子浩) 歡迎分享,但需在文章鮮明處留下原文地址。
本文將要講述如何使用IdentityServer4對API授權保護以及如何攜帶Token進行訪問受保護的API,通過HttpClient或Http請求中的body這些我們都可以達到。那么廢話不多說,開始吧~
首先我們一定要知道,我們訪問要訪問一個受安全限制的API的鎖子是在一個專門的IdentityServer4驗證服務器。所以呢,我們需要創建一個認證服務器。首先我們創建一個API項目。
創建完成之后,我們再創建一個Config.cs,當然這個名字你隨意,但你需要在DI注入的時候與其對應。在 GetSoluction 中定義了我們的API,也就是受保護的鎖子,第一個參數是name,也就是Api的名稱,那么后面是顯示的名字,也就是DisplayName。在 GetClients 當中我們定義了受信任的客戶端,其中有客戶端的ID,授權方式,客戶端加密方式,通過 AllowedScopes 還定義了這個客戶端可以訪問的API。
using IdentityServer4.Models; using System.Collections.Generic; namespace IdentityServerSolution { /// <summary> /// zaranet 2019.1.26 14.10 create this file /// Config是IdentityServer的配置文件,一會我們需要注冊到DI層。 /// </summary> public class Config { /// <summary> /// 這個ApiResource參數就是我們Api /// </summary> /// <returns></returns> public static IEnumerable<ApiResource> GetSoluction() { return new[] { new ApiResource("api1", "MY API") }; } public static IEnumerable<Client> GetClients() { return new List<Client> { new Client { ClientId = "Client", AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets = { new Secret("secret".Sha256()), }, AllowedScopes = {"api1"} } }; } } }
我們現在已經寫好了關於IdentityServer4服務器的配置文件,那么我們還需要去依賴注入到.NET Core管道中,現在我們看一下定義。
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer() .AddInMemoryApiResources(Config.GetSoluction()) .AddInMemoryClients(Config.GetClients()) .AddDeveloperSigningCredential(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //添加認證中間件 app.UseIdentityServer(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); }
就是這樣 - 如果您運行服務器並瀏覽瀏覽器 http://localhost:您的端口/.well-known/openid-configuration ,您應該會看到所謂的發現文檔。客戶端和API將使用它來下載必要的配置數據。
首次啟動時,IdentityServer將為您創建一個開發人員簽名密鑰,它是一個名為的文件tempkey.rsa
。您不必將該文件檢入源代碼管理中,如果該文件不存在,將重新創建該文件。
以下是用PostMan進行的測試,以HttpPost方式進行請求,並在Http Body中進行編輯請求體上下文,測試結果如下。如果三個參數沒有問題就返回token,如果其中三個參數有一個寫錯,那么就會返回400錯誤(error:invalid_client)。
下面在API項目中添加控制器:
[Route("identity")] [Authorize] [ApiController] public class IdentityController : ControllerBase { [HttpGet] public IActionResult Get() { return new JsonResult(from c in User.Claims select new { c.Type, c.Value }); } }
稍后將使用此控制器來測試授權要求,以及通過API的眼睛可視化聲明身份。現在我們將身份驗證服務添加到DI和身份驗證中間價到管道中,驗證傳入令牌以確保它來自受信任的頒發者。
將Startup更新為如下所示:
public void ConfigureServices(IServiceCollection services) { services.AddMvcCore() .AddAuthorization() .AddJsonFormatters(); services.AddAuthentication("Bearer") .AddJwtBearer("Bearer", options => { options.Authority = "http://localhost:58653"; options.RequireHttpsMetadata = false; options.Audience = "api1"; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseAuthentication(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); }
AddAuthentication 是為了用於將IdentityServer4訪問令牌驗證處理程序將在DI中提供身份驗證服務。 UseAuthentication 將身份驗證中間件添加到管道中,以便在每次調用主機時自動執行身份驗證。如果你現在轉到 http://localhost:prot/identity
中是401錯誤的話,說明API已經得到了保護。配置成功了!,現在我們要創建我們的客戶端了。去訪問受保護的API需要攜帶鑰匙,那么這個鑰匙術語叫做令牌,那就是通往大門的令牌!現在立刻創建一個控制台程序,使用令牌訪問API。
首先我們需要安裝IdentityModel,因為它可以替我們找到元數據。
IdentityModel包括用於發現端點的客戶端庫。這樣您只需要知道IdentityServer的基地址 - 可以從元數據中讀取實際的端點地址:
var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync("http://localhost:58653"); if (disco.IsError) { Console.WriteLine(disco.Error); return; }
接下來,您可以使用發現文檔中的信息來請求令牌:
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest { Address = disco.TokenEndpoint, ClientId = "Client", //id ClientSecret = "secret", //pwd Scope = "api1" //請求的api }); if (tokenResponse.IsError) { Console.WriteLine(tokenResponse.Error); return; }
要將訪問令牌發送到API,通常使用HTTP Authorization標頭。這是使用 SetBearerToken 擴展方法完成的:
var Apiclient = new HttpClient(); Apiclient.SetBearerToken(tokenResponse.AccessToken); var response = await client.GetAsync("http://localhost:58653/identity"); if (!response.IsSuccessStatusCode) { Console.WriteLine(response.StatusCode); } else { var content = await response.Content.ReadAsStringAsync(); Console.WriteLine(JArray.Parse(content)); }
就這樣,我們啟動結果如下,啟動順序,應先啟動身份認證平台,然后再啟動API,在啟動控制台調試工具。
就這樣一個簡單的IdentityServer4身份認證平台就OK了,現在是不是想要迫切的試一下呢?哈哈,關於源代碼,我放到我的Coding中了,地址是:https://coding.net/u/zaranet/p/IdentitySERVER,當然不要看着簡單,還是自己敲一下吧,如果你一點都沒有碰過IdentityServer的話。下面我們在回顧一下。
我們在 IdentityServerSoluction 中定義了 Config 文件,用於Id4的配置,主要功能是為了認證模型,其中還設置了Client請求文中的 ClientId 這些參數等等。那么 IdentItyAPI 就是我們的項目服務,其中通過 Authorize 標記的都是具有安全保護的API控制器,那么我們就需要去獲取我們的IdentityServerSoluction 中的驗證,這樣我們才可以訪問,那么我們就用了.NET Core控制台程序去模擬了這個過程,其中涉及了 HttpClient 相關知識。那么最后返回了我們的相關 token ,這樣,我們可以根據 token 去獲取我們想要的API服務了!
最后祝大家春運快樂。下一篇干貨在等大家噢!