微服務閘道器Ocelot加入IdentityServer4鑑權-.NetCore(.NET5)中使用

包子wxl發表於2021-10-21

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務註冊,服務發現

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-閘道器Ocelot+Consul

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly快取、限流、熔斷、降級

微服務閘道器Ocelot加入IdentityServer4鑑權-.NetCore(.NET5)中使用

一、簡介

 

 

 

 

 描述:微服務閘道器中,需要對訪問的介面進行身份校驗後再轉發請求,閘道器中鑑權的方式有很多種,這裡介紹的是常用的IdentityServer4鑑權新增到Ocelot閘道器中,同時下游的服務也要做身份校驗,

      防止請求繞過閘道器直接請求下游服務。

二、建立IdentityServer4專案

這裡重點不是說IdentityServer4,所以這裡建一個簡單的示例專案。

1.建立一個Identity4.Api專案

引入NugGet包

IdentityServer4
IdentityServer4.Storage

這裡用的都是4.1.2版本

2.在專案中建立一個config靜態類

 /// <summary>
    /// 配置
    /// </summary>
    public class Config
    {
        /// <summary>
        /// 定義作用域
        /// </summary>
        public static IEnumerable<ApiScope> ApiScopes =>
            new ApiScope[]
            {
            new ApiScope("gatewayScope"),
            new ApiScope("scope2")
            };

        public static IEnumerable<ApiResource> ApiResources =>
            new ApiResource[]
            {

                new ApiResource("server1","服務1")
                {
                    //4.x必須寫
                    Scopes = { "gatewayScope" }
                },
            };

        public static IEnumerable<Client> Clients =>
            new Client[]
            {
            new Client
            {
                ClientId = "client_test",
                ClientName = "測試客戶端",

                AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
                ClientSecrets = { new Secret("secret_test".Sha256()) },

                AllowedScopes = { "gatewayScope" }
            },
            };

        /// <summary>
        /// 測試的賬號和密碼
        /// </summary>
        /// <returns></returns>
        public static List<TestUser> GetTestUsers()
        {
            return new List<TestUser>
    {
        new TestUser()
        {
             SubjectId = "1",
             Username = "test",
             Password = "123456"
        }
    };
        }
    }

 3.在Startup.cs的ConfigureServices()方法中加入

 public void ConfigureServices(IServiceCollection services)
        {
            #region 記憶體方式
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryApiResources(Config.ApiResources)
                .AddInMemoryClients(Config.Clients)
                .AddInMemoryApiScopes(Config.ApiScopes) //4.x新加
                .AddTestUsers(Config.GetTestUsers());
            #endregion
            services.AddControllersWithViews();
        }

4.在Startup.cs的Configure()方法中加入

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();
            app.UseIdentityServer();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

到這裡一個IdentitySever4的鑑權中心就建好了,執行起來,用Postman測試獲取token。

 

 token獲取成功,說明IdentityServer4的鑑權中心沒問題了。

三、Ocelot中加入IdentityServer4認證

Ocelot閘道器預設已經整合了Id4的,我們需要做的事情有:

1.在配置中加入IdentityServer4的資訊,ocelog.json中加入


{
    "Routes": [
      {
        //轉發到下游服務地址--url變數
        "DownstreamPathTemplate": "/api/{url}",
        //下游http協議
        "DownstreamScheme": "http",
        //負載方式,
        "LoadBalancerOptions": {
          "Type": "RoundRobin" // 輪詢
        },
        //上游地址
        "UpstreamPathTemplate": "/T1/{url}", //閘道器地址--url變數   //衝突的還可以加權重Priority
        "UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
        "UseServiceDisConvery": true, //使用服務發現
        "ServiceName": "api", //Consul服務名稱
        //熔斷設定,熔斷器使用Polly
        "QoSOptions": {
          "ExceptionsAllowedBeforeBreaking": 3, //允許多少個異常請求
          "DurationOfBreak": 10000, // 熔斷的時間10s,單位為ms
          "TimeoutValue": 5000 //單位ms,如果下游請求的處理時間超過多少則自動將請求設定為超時 預設90秒
        },
        //鑑權
        "AuthenticationOptions": {
          "AuthenticationProviderKey": "Bearer", //指定一個key
          "AllowedScopes": [ "gatewayScope" ] //id4的作用域名稱
        }
      }
    ],
    "GlobalConfiguration": {
      //Ocelot應用對外地址
      "BaseUrl": "http://172.16.2.9:5200",
      "ServiceDiscoveryProvider": {
        //Consul地址
        "Host": "172.16.2.84",
        //Consul埠
        "Port": 8500,
        "Type": "Consul" //由Consul提供服務發現,每次請求Consul
      }
    }
  }

2.把Id4加入到IOC中

新增NuGet包

IdentityServer4.AccessTokenValidation

Ocelot專案Startup.cs中的ConfigureServices()方法加上

 public void ConfigureServices(IServiceCollection services)
        {
            var authenticationProviderKey = "Bearer"; //這個為上面配置裡的key
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddIdentityServerAuthentication(authenticationProviderKey, options =>
                {
                    options.Authority = "http://localhost:5000";//id4服務地址
                    options.ApiName = "server1";//id4 api資源裡的apiname
                    options.RequireHttpsMetadata = false; //不使用https
                    options.SupportedTokens = SupportedTokens.Both;
                });
            services.AddOcelot()
                .AddConsul()
                .AddPolly();
        }

  

到這裡,Ocelot閘道器配置Id4就配好了。

3.測試驗證

先測試加了Id4後,不帶token訪問下閘道器

 

 

 可以看到,報了401,沒許可權訪問,再試一下把上面id4取到的token帶上訪問。

 

 發現可以訪問成功了。這Ocelot中加入Id4校驗就完成了。

四、下游服務加入IdentityServer4認證

為什麼下游服務要加身份校驗呢,因為請求可能繞過閘道器直接訪問下游服務,沒有驗證就會出問題了。

1.配置

只需要在startup.cs中的ConfigureServices中加入上面的程式碼,去掉AuthenticationProviderKey

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                         .AddIdentityServerAuthentication(options =>
                         {
                             options.Authority = "http://localhost:5000";//id4服務地址
                             options.ApiName = "server1";//id4 api資源裡的apiname
                             options.RequireHttpsMetadata = false; //不使用https
                             options.SupportedTokens = SupportedTokens.Both;
                         });
            services.AddControllers().AddJsonOptions(cfg =>
            {
                cfg.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
            });
          
            services.AddSingleton<OrderService>();

        }

然後在Configure()方法中,    app.UseRouting();後面加上  app.UseAuthentication();

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
            //Consul註冊
            app.UseConsul(Configuration);
        }

 

然後在要校驗的地方加上[Authorize]

 

 

2.校驗不帶token直接訪問下游服務

  

 

 顯示沒許可權,再試帶上token直接訪問下游服務。

 

 

 

 很好,成功訪問,然後再試下通過閘道器訪問是否能正常訪問。

 

也成了,全部配置完成!

 

原始碼地址:https://github.com/weixiaolong325/Ocelot-Consul-Polly-Id4.Demo

相關文章