.NET Core 微服務—API網關(Ocelot) 教程 [三]

前言:

 前一篇文章《.NET Core 微服務—API網關(Ocelot) 教程 [二]》已經讓Ocelot和目錄api(Api.Catalog)、訂單api(Api.Ordering)經過網關方式運行起來了。但在平常開發中Api並非全部人都能訪問的,是添加了認證、受權的。那麼本篇文章就將繼續介紹Ocelot如何和 IdentityServer4 認證服務如何配合使用的。html

建立認證服務(Api.IdentityServer)git

 一、建立一個空的WebApi項目-Api.IdentityServer,並添加IdentityServer4項目引用:以下圖:github

Install-Package IdentityServer4

  

 二、要啓用IdentityServer服務,不只要把 IdentityServer 註冊到容器中, 還須要配置一下內容:數據庫

  •  Authorization Server 保護了哪些 API (資源);
  • 哪些客戶端 Client(應用) 可使用這個 Authorization Server;json

  • 指定可使用 Authorization Server 受權的 Users(用戶)api

  a) 建立文件 InMemoryConfig.cs,用於設置以上相關內容:app

 1 using IdentityServer4;
 2 using IdentityServer4.Models;
 3 using IdentityServer4.Test;
 4 using System;
 5 using System.Collections.Generic;
 6 using System.Linq;
 7 using System.Threading.Tasks;
 8 
 9 namespace Api.IdentityServer
10 {
11     public class InMemoryConfig
12     {
13         public static IEnumerable<IdentityResource> GetIdentityResourceResources()
14         {
15             return new List<IdentityResource>
16             {
17                 //必需要添加,不然報無效的scope錯誤
18                 new IdentityResources.OpenId(),
19             };
20         }
21 
22         /// <summary>
23         /// api資源列表
24         /// </summary>
25         /// <returns></returns>
26         public static IEnumerable<ApiResource> GetApiResources()
27         {
28             //可訪問的API資源(資源名,資源描述)
29             return new List<ApiResource>
30             {
31                 new ApiResource("Api.Catalog", "Api.Catalog"),
32                 new ApiResource("Api.Ordering", "Api.Ordering")
33             };
34         }
35 
36         /// <summary>
37         /// 客戶端列表
38         /// </summary>
39         /// <returns></returns>
40         public static IEnumerable<Client> GetClients()
41         {
42             return new List<Client>
43             {
44                 new Client
45                 {
46                     ClientId = "client_Catalog", //訪問客戶端Id,必須惟一
47                     //使用客戶端受權模式,客戶端只須要clientid和secrets就能夠訪問對應的api資源。
48                     AllowedGrantTypes = GrantTypes.ClientCredentials,
49                     ClientSecrets =
50                     {
51                         new Secret("secret".Sha256())
52                     },
53                     AllowedScopes = { "Api.Catalog", IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile }
54                 },
55                 new  Client
56                 {
57                     ClientId = "client_Ordering",
58                     ClientSecrets = new [] { new Secret("secret".Sha256()) },
59                     //這裏使用的是經過用戶名密碼和ClientCredentials來換取token的方式. ClientCredentials容許Client只使用ClientSecrets來獲取token. 這比較適合那種沒有用戶參與的api動做
60                     AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
61                     AllowedScopes = { "Api.Ordering", IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile }
62                 }
63             };
64         }
65 
66         /// <summary>
67         /// 指定可使用 Authorization Server 受權的 Users(用戶)
68         /// </summary>
69         /// <returns></returns>
70         public static IEnumerable<TestUser> Users()
71         {
72             return new[]
73             {
74                     new TestUser
75                     {
76                         SubjectId = "1",
77                         Username = "cba",
78                         Password = "abc"
79                     }
80             };
81         }
82     }
83 }
View Code

     GetApiResources:這裏指定了name和display name, 之後api使用authorization server的時候, 這個name必定要一致asp.net

  GetClients: 認證客戶端列表ide

  Users: 這裏的內存用戶的類型是TestUser, 只適合學習和測試使用, 實際生產環境中仍是須要使用數據庫來存儲用戶信息的, 例如接下來會使用asp.net core identity. TestUser的SubjectId是惟一標識.微服務

 b) 在Startup.cs中啓用IdentityServer服務

 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.Mvc;
 8 using Microsoft.Extensions.Configuration;
 9 using Microsoft.Extensions.DependencyInjection;
10 using Microsoft.Extensions.Hosting;
11 using Microsoft.Extensions.Logging;
12 
13 namespace Api.IdentityServer
14 {
15     public class Startup
16     {
17         public Startup(IConfiguration configuration)
18         {
19             Configuration = configuration;
20         }
21 
22         public IConfiguration Configuration { get; }
23 
24         // This method gets called by the runtime. Use this method to add services to the container.
25         public void ConfigureServices(IServiceCollection services)
26         {
27             services.AddControllers();
28 
29             services.AddIdentityServer()
30                 .AddDeveloperSigningCredential()                    
31 .AddInMemoryApiResources(InMemoryConfig.GetApiResources())
32                 .AddInMemoryClients(InMemoryConfig.GetClients())
33                 .AddTestUsers(InMemoryConfig.Users().ToList());
34 
35             services.AddAuthentication();//配置認證服務
36         }
37 
38         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
39         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
40         {
41             if (env.IsDevelopment())
42             {
43                 app.UseDeveloperExceptionPage();
44             }
45             app.UseStaticFiles();
46             app.UseRouting();
47 
48             app.UseIdentityServer();
49 
50             app.UseAuthentication();
51             app.UseAuthorization();
52 
53             app.UseEndpoints(endpoints =>
54             {
55                 endpoints.MapControllers();
56             });
57         }
58     }
59 }
View Code

      

爲ocelot項目集成IdentityServer

 一、添加IdentityServer4.AccessTokenValidation的包,也能夠經過程序包管理控制檯執行如下命令 

    Install-Package IdentityServer4.AccessTokenValidation

    添加包引用後,在Startup中的 ConfigureServices 中分別註冊兩個認證方案 Configure 中配置IdentityServer服務。    

        public void ConfigureServices(IServiceCollection services)
        {

            services.AddAuthentication()
              .AddJwtBearer("Api.Catalog", i =>
              {
                  i.Audience = "Api.Catalog";
                  i.Authority = "http://localhost:5332";
                  i.RequireHttpsMetadata = false;
              }).AddJwtBearer("Api.Ordering", y =>
              {
                  y.Audience = "Api.Ordering";
                  y.Authority = "http://localhost:5331";
                  y.RequireHttpsMetadata = false;
              });

            services.AddOcelot();//注入Ocelot服務

            services.AddControllers();
        }

  

 二、修改ocelot配置文件,在Routes中添加受權信息

  調整ApiGateway.Ocelot項目中ocelot.json配置文件以下:  

{
  "GlobalConfiguration": {

  },
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/{controller}/{action}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5331
        }
      ],
      "UpstreamPathTemplate": "/Catalog/{controller}/{action}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      //受權信息 "AuthenticationOptions": { "AuthenticationProviderKey": "Api.Catalog", "AllowedScopes": [] }
    },
    {
      "DownstreamPathTemplate": "/api/{controller}/{action}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5332
        }
      ],
      "UpstreamPathTemplate": "/Ordering/{controller}/{action}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      //受權信息 "AuthenticationOptions": { "AuthenticationProviderKey": "Api.Ordering", "AllowedScopes": [] }
    }
  ]
}

Ocelot會去檢查Routes是否配置了AuthenticationOptions節點。若是有會根據配置的認證方案進行身份認證。若是沒有則不進行身份認證。
AuthenticationProviderKey 是剛纔註冊的認證方案。
AllowedScopes 是 AllowedScopes中配置的受權訪問範圍。

驗證效果

 一、根據網關設置訪問:目錄api:http://localhost:5330/Ordering/Values/1 
   如圖:401 Unauthorized 未認證

  

 二、先獲取Token後再訪問該接口:

   

   根據獲取Token在http://localhost:5330/Ordering/Values/1 請求時,添加認證頭信息,便可請求成功

  

 

 

 

回顧總結

  一、在IdentityServer註冊相關資源服務和客戶端信息。

  二、Ocelot經過註冊認證方案,在配置文件中指定路由的認證方案

  三、該認證是在Ocelot網關層對相關資源進行認證,並不是資源服務認證

  四、認證調用失敗時,嘗試把IdentityServer包版本下降嘗試 

 

 源碼:https://github.com/cwsheng/ocelot.Demo.git

相關文章
相關標籤/搜索