快速入門IdentityServer4

  • 概述

    • 將 IdentityServer 新增到 ASP.NET Core 應用程式
    • 配置 IdentityServer
    • 為各種客戶發行代幣
    • 保護 Web 應用程式和 API
    • 新增對基於 EntityFramework 的配置的支援
    • 新增對 ASP.NET 標識的支援
  • 準備
    • 安裝模板

      控制檯視窗輸入該命令,下載 IdentityServer 模板

dotnet new -i IdentityServer4.Templates //
    • 建立專案

      開啟控制檯視窗,請在控制檯視窗鍵入以下命令

md quickstart    //建立資料夾,資料夾名稱quickstart
cd quickstart //進入資料夾quickstart md src //建立資料夾,資料夾名稱src
cd src //進入資料夾src dotnet new is4empty -n IdentityServer //建立空專案,專案名稱IdentityServer

      命令執行完成後,將會建立以下檔案

        IdentityServer.csproj- 專案檔案和一個Properties\launchSettings.json檔案

        Program.csStartup.cs- 主應用程式入口點

        Config.cs - IdentityServer 資源和客戶端配置檔案

      如果需要使用Visual Studio作為開發工具,我們還需要建立解決方案檔案,命令如下:

dotnet new sln -n Quickstart

       我們需要將檔案新增至解決方案,命令如下:(請注意路徑是否正確)

dotnet sln add .\src\IdentityServer\IdentityServer.csproj
  • 開始學習

     專案建立成功之後,將會為我們建立config 檔案,Config檔案的程式碼如下:

 1 using IdentityServer4.Models;
2 using System.Collections.Generic;
3
4 namespace IdentityServer
5 {
6 public static class Config
7 {
8 public static IEnumerable<IdentityResource> IdentityResources =>
9 new IdentityResource[]
10 {
11 new IdentityResources.OpenId()
12 };
13
14 public static IEnumerable<ApiScope> ApiScopes =>
15 new ApiScope[]
16 { };
17
18 public static IEnumerable<Client> Clients =>
19 new Client[]
20 { };
21 }
22 }
  • 自定義API範圍
1  public static IEnumerable<ApiScope> ApiScopes =>
2 new List<ApiScope>
3 {
4 new ApiScope("api1", "MyApiName")
5 };
//ApiScope建構函式提供兩個引數,第一個引數為name,第二個引數為displayname

    如果您在生產環境種使用自定義API範圍,您為您的API提供一個邏輯名稱很重要,開發人員將使用它通過您的身份伺服器請求您的API,它應該用簡單的術語向開發人員描述您的api,displayname為使用者提供apiScope的描述名稱

  • 定義客戶端

     我們將要定義一個客戶端應用程式,我們將用它來訪問我們的API,對於這種情況,客戶端沒有互動式使用者,並將使用IdentityServer使用客戶端金鑰進行身份驗證。為此我們需要新增一個客戶端

 

 1 public static IEnumerable<Client> Clients =>
2 new[]
3 {
4 new Client
5 {
6 ClientId = "client",
7
8 AllowedGrantTypes=GrantTypes.ClientCredentials,
9
10 ClientSecrets =
11 {
12 new Secret("secret","sha256")
13 },
14 AllowedScopes = { "api1" }
15 }
16 };

    您可以將 ClientId 和 ClientSecret 視為應用程式本身的登入名和密碼。它向身份伺服器標識您的應用程式,以便它知道哪個應用程式正在嘗試連線到它。

  • 配置身份伺服器

    在Startup.cs檔案中的ConfigureServices方法種定義資源和客戶端,程式碼如下:

 1  public void ConfigureServices(IServiceCollection services)
2 {
3 // uncomment, if you want to add an MVC-based UI
4 //services.AddControllersWithViews();
5
6 var builder = services.AddIdentityServer(options =>
7 {
8 // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
9 options.EmitStaticAudienceClaim = true;
10 })
11 .AddInMemoryIdentityResources(Config.IdentityResources)
12 .AddInMemoryApiScopes(Config.ApiScopes)
13 .AddInMemoryClients(Config.Clients);
14
15 // not recommended for production - you need to store your key material somewhere secure
16 builder.AddDeveloperSigningCredential();
17 }

     配置您的身份伺服器之後,訪問路徑https://localhost:5001/.well-known/openid-configuration,我們將會看到發現文件,發現文件是身份伺服器種的標準節點,您的客戶端和API將使用該文件來檢視必要的配置資料,節點文件如下:

 1 {
2 "issuer":"https://localhost:5001",
3 "jwks_uri":"https://localhost:5001/.well-known/openid-configuration/jwks",
4 "authorization_endpoint":"https://localhost:5001/connect/authorize",
5 "token_endpoint":"https://localhost:5001/connect/token",
6 "userinfo_endpoint":"https://localhost:5001/connect/userinfo",
7 "end_session_endpoint":"https://localhost:5001/connect/endsession",
8 "check_session_iframe":"https://localhost:5001/connect/checksession",
9 "revocation_endpoint":"https://localhost:5001/connect/revocation",
10 "introspection_endpoint":"https://localhost:5001/connect/introspect",
11 "device_authorization_endpoint":"https://localhost:5001/connect/deviceauthorization",
12 "frontchannel_logout_supported":true,
13 "frontchannel_logout_session_supported":true,
14 "backchannel_logout_supported":true,
15 "backchannel_logout_session_supported":true,
16 "scopes_supported":[
17 "openid",
18 "api1",
19 "offline_access"
20 ],
21 "claims_supported":[
22 "sub"
23 ],
24 "grant_types_supported":[
25 "authorization_code",
26 "client_credentials",
27 "refresh_token",
28 "implicit",
29 "urn:ietf:params:oauth:grant-type:device_code"
30 ],
31 "response_types_supported":[
32 "code",
33 "token",
34 "id_token",
35 "id_token token",
36 "code id_token",
37 "code token",
38 "code id_token token"
39 ],
40 "response_modes_supported":[
41 "form_post",
42 "query",
43 "fragment"
44 ],
45 "token_endpoint_auth_methods_supported":[
46 "client_secret_basic",
47 "client_secret_post"
48 ],
49 "id_token_signing_alg_values_supported":[
50 "RS256"
51 ],
52 "subject_types_supported":[
53 "public"
54 ],
55 "code_challenge_methods_supported":[
56 "plain",
57 "S256"
58 ],
59 "request_parameter_supported":true
60 }

   在第一次啟動時,IdentityServer 會為你建立一個開發者簽名金鑰,它是一個名為tempkey.jwk. 您不必將該檔案簽入您的原始碼管理,如果它不存在,它將被重新建立

  • 新增API測試

     建立API專案,命令如下:

dotnet new webapi -n Api

    將API專案新增至解決方案

dotnet sln add .\src\Api\Api.csproj

    修改API專案的應用配置,修改執行埠號,我們可以通過編輯Properties 資料夾中的launchSettings.json檔案來執行此操作,將應用程式的URL設定更改為:

"applicationUrl": "https://localhost:6001"
  • 新增控制器

   我們新建一個類,為IdentityController,此測試類將用於測試授權要求,以及通過API視覺化身份識別

  

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Threading.Tasks;
5 using Microsoft.AspNetCore.Authorization;
6 using Microsoft.AspNetCore.Mvc;
7
8 namespace Api.Controllers
9 {
10 [Route("identity")]
11 [Authorize]
12 public class IdentityController: ControllerBase
13 {
14 public IActionResult Get()
15 {
16 return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
17 }
18 }
19 }

  新增NuGet包依賴專案:Microsoft.AspNetCore.Authentication.JwtBearer,我們可以手動新增,也可以執行如下命令:

dotnet add .\\src\\api\\Api.csproj package Microsoft.AspNetCore.Authentication.JwtBearer
  • 配置

  最後一步是將身份驗證服務新增到DI(依賴注入) 並將身份驗證中介軟體新增到管道中,這些操作將:

    • 驗證傳入的令牌以確保它來自受信任者的發行者
    • 驗證令牌是否有效與此API一起使用

  我們檢視以下API中的Startup程式碼,我們將其更新如下:

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Threading.Tasks;
5 using Microsoft.AspNetCore.Builder;
6 using Microsoft.AspNetCore.Hosting;
7 using Microsoft.AspNetCore.HttpsPolicy;
8 using Microsoft.AspNetCore.Mvc;
9 using Microsoft.Extensions.Configuration;
10 using Microsoft.Extensions.DependencyInjection;
11 using Microsoft.Extensions.Hosting;
12 using Microsoft.Extensions.Logging;
13 using Microsoft.IdentityModel.Tokens;
14 using Microsoft.OpenApi.Models;
15
16 namespace Api
17 {
18 public class Startup
19 {
20 public Startup(IConfiguration configuration)
21 {
22 Configuration = configuration;
23 }
24
25 public IConfiguration Configuration { get; }
26
27 // This method gets called by the runtime. Use this method to add services to the container.
28 public void ConfigureServices(IServiceCollection services)
29 {
30
31 services.AddControllers();
32 services.AddSwaggerGen(c =>
33 {
34 c.SwaggerDoc("v1", new OpenApiInfo { Title = "Api", Version = "v1" });
35 });
36
37 services.AddAuthentication("Bearer").AddJwtBearer("Bearer", options =>
38 {
39 options.Authority = "https://localhost:5001";
40
41 options.TokenValidationParameters = new TokenValidationParameters
42 {
43 ValidateAudience = false
44 };
45 });
46
47 }
48
49 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
50 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
51 {
52 if (env.IsDevelopment())
53 {
54 app.UseDeveloperExceptionPage();
55 app.UseSwagger();
56 app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Api v1"));
57 }
58
59 app.UseHttpsRedirection();
60
61 app.UseRouting();
62
63 app.UseAuthentication();
64 app.UseAuthorization();
65
66 app.UseEndpoints(endpoints =>
67 {
68 endpoints.MapControllers();
69 });
70
71 }
72 }
73 }

   AddAuthentication將身份驗證服務新增到 DI 並配置Bearer為預設方案。

   UseAuthentication 將身份驗證中介軟體新增到管道中,因此每次呼叫主機時都會自動執行身份驗證。

   UseAuthorization 新增授權中介軟體以確保匿名客戶端無法訪問我們的 API 端點。

   https://localhost:6001/identity在瀏覽器上導航到控制器應返回 401 狀態程式碼。這意味著您的 API 需要憑證並且現在受 IdentityServer 保護。