1. 程式人生 > >Ocelot簡易教程(五)之整合IdentityServer認證以及授權

Ocelot簡易教程(五)之整合IdentityServer認證以及授權

Ocelot簡易教程目錄

最近比較懶,所以隔了N天才來繼續更新第五篇Ocelot簡易教程,本篇教程會先簡單介紹下官方文件記錄的內容然後在前幾篇文件程式碼的基礎上進行例項的演示。目的是為了讓小白也能按照步驟把程式碼跑起來。當然,在開始之前你要對IdentityServer有一定的瞭解,並且能夠進行IdentityServer的整合,如果你還不會整合IdentityServer的話還是先看看我的這篇Asp.NetCoreWebApi圖片上傳介面(二)整合IdentityServer4授權訪問(附原始碼)文章吧。裡面有一步一步的整合IdentityServer的例項。

好了,廢話說完了,那就讓我們開始進入今天的主題吧!Ocelot認證與授權。

概念表述

認證

為了驗證ReRoutes並隨後使用Ocelot的任何基於宣告的功能,例如授權或使用令牌中的值修改請求。 使用者必須像往常一樣在他們的Startup.cs中註冊認證服務,惟一的不同是他們需要給每個認證註冊提供一個方案,例如

public void ConfigureServices(IServiceCollection services)
{
    var authenticationProviderKey = "OcelotKey";

    services.AddAuthentication()
        .AddJwtBearer(authenticationProviderKey, x =>
        {
        });
}

在此示例中,OcelotKey是此提供程式已註冊的方案。然後我們將其對映到配置中的ReRoute,例如

"ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 1001
        },
        {
          "Host": "localhost",
          "Port": 1002
        }
      ],
      "UpstreamPathTemplate": "/{everything}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "OcelotKey",
        "AllowedScopes": []
      }
    }
  ]

當Ocelot執行時,它將檢視此ReRoutes中 AuthenticationOptions節點下面的AuthenticationProviderKey並檢查是否有使用給定金鑰註冊的身份驗證提供程式。如果沒有,那麼Ocelot不會啟動,如果有的話ReRoute將在執行時使用該提供者。

如果對ReRoute進行了身份驗證,則Ocelot將在執行身份驗證中介軟體時呼叫與其關聯的認證方案。如果請求失敗,則認證Ocelot返回http的狀態程式碼為401即未授權狀態。

JWT令牌

如果您想使用JWT令牌進行身份驗證,可能來自OAuth之類的提供程式,您可以正常註冊您的身份驗證中介軟體,例如

public void ConfigureServices(IServiceCollection services)
{
    var authenticationProviderKey = "OcelotKey";

    services.AddAuthentication()
        .AddJwtBearer(authenticationProviderKey, x =>
        {
            x.Authority = "test";
            x.Audience = "test";
        });

    services.AddOcelot();
}

然後將身份驗證提供程式金鑰對映到配置中的ReRoute,例如

"ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 1001
        },
        {
          "Host": "localhost",
          "Port": 1002
        }
      ],
      "UpstreamPathTemplate": "/{everything}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "OcelotKey",
        "AllowedScopes": []
      }
    }
  ]

Identity Server Bearer Tokens認證

接下來上今天的主角了。identityServer認證方式。為了使用IdentityServer承載令牌,請按照慣例在ConfigureServices 中使用方案(金鑰)註冊您的IdentityServer服務。 如果您不明白如何操作,請訪問IdentityServer文件。或者檢視我的這篇Asp.NetCoreWebApi圖片上傳介面(二)整合IdentityServer4授權訪問(附原始碼)文章。

 var authenticationProviderKey = "OcelotKey";
            var identityServerOptions = new IdentityServerOptions();
            Configuration.Bind("IdentityServerOptions", identityServerOptions);
            services.AddAuthentication(identityServerOptions.IdentityScheme)
                .AddIdentityServerAuthentication(authenticationProviderKey, options =>
                {
                    options.RequireHttpsMetadata = false; //是否啟用https
                    options.Authority = $"http://{identityServerOptions.ServerIP}:{identityServerOptions.ServerPort}";//配置授權認證的地址
                    options.ApiName = identityServerOptions.ResourceName; //資源名稱,跟認證服務中註冊的資源列表名稱中的apiResource一致
                    options.SupportedTokens = SupportedTokens.Both;
                }
                );
            services.AddOcelot()//注入Ocelot服務
                    .AddConsul();

然後將身份驗證提供程式金鑰對映到配置中的ReRoute,例如

"ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 1001
        },
        {
          "Host": "localhost",
          "Port": 1002
        }
      ],
      "UpstreamPathTemplate": "/{everything}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "OcelotKey",
        "AllowedScopes": []
      }
    }
  ]

允許訪問的範圍(Allowed Scopes)

如果將範圍新增到AllowedScopes,Ocelot將獲得類型範圍的所有使用者宣告(從令牌中),並確保使用者具有列表中的所有範圍。

這是一種基於範圍限制對ReRoute訪問的方式。(我也沒用過這種方式,感覺有點類似IdentityServer Scope的概念)

例項演示整合IdentityServer

  1. 新建一個OcelotDemo.Auth asp.net core web api專案

  2. 在閘道器專案OcelotDemo中新增Nuget包

    Install-Package IdentityServer4.AccessTokenValidation   
  3. 在OcelotDemo專案中的Startup.cs中加入identityServer驗證,如下所示:

    var authenticationProviderKey = "OcelotKey";
                var identityServerOptions = new IdentityServerOptions();
                Configuration.Bind("IdentityServerOptions", identityServerOptions);
                services.AddAuthentication(identityServerOptions.IdentityScheme)
                    .AddIdentityServerAuthentication(authenticationProviderKey, options =>
                    {
                        options.RequireHttpsMetadata = false; //是否啟用https
                        options.Authority = $"http://{identityServerOptions.ServerIP}:{identityServerOptions.ServerPort}";//配置授權認證的地址
                        options.ApiName = identityServerOptions.ResourceName; //資源名稱,跟認證服務中註冊的資源列表名稱中的apiResource一致
                        options.SupportedTokens = SupportedTokens.Both;
                    }
                    );
                services.AddOcelot()//注入Ocelot服務
                        .AddConsul();
  4. 在ocelot.json中需要加入驗證的ReRoute中,修改為如下的配置程式碼:

    "ReRoutes": [
        {
          "DownstreamPathTemplate": "/api/{everything}",
          "DownstreamScheme": "http",
          "DownstreamHostAndPorts": [
            {
              "Host": "localhost",
              "Port": 1001
            },
            {
              "Host": "localhost",
              "Port": 1002
            }
          ],
          "UpstreamPathTemplate": "/{everything}",
          "UpstreamHttpMethod": [ "Get", "Post" ],
          "LoadBalancerOptions": {
            "Type": "RoundRobin"
          },
          "AuthenticationOptions": {
            "AuthenticationProviderKey": "OcelotKey",
            "AllowedScopes": []
          }
        }
      ]
  5. 開啟PostMan測試一下程式碼吧,首先訪問一下http://localhost:1000/values 這時候返回的結果是401未授權的狀態,如下圖所示:

    1539780575952

  6. 然後訪問我們上面新建的IdentityServer伺服器並獲取Token。如下圖所示配置對應的引數進行獲取:

    1539780272769

  7. 然後使用我們獲取到的access_token進行Ocelot閘道器介面的訪問,如下所示進行配置:

    1539780805247

    可以看到結果返回了200程式碼,並且結果在Good以及Order之間進行切換。因為Ocelot.json檔案中對路由進行了RoundRobin的負載均衡的策略。

授權

Ocelot支援基於宣告的授權,該授權在身份驗證後執行。這意味著如果您有要授權的Url,則可以將以下內容新增到ReRoute配置中。

"RouteClaimsRequirement": {
    "UserType": "registered"
}

在此示例中,當呼叫授權中介軟體時,Ocelot將檢查使用者是否具有宣告型別UserType以及是否已註冊該宣告的值。如果不是,則使用者將不被授權,並且將響應403禁止訪問的狀態碼。

當然這種授權的方式在大部分業務場景中都是不適用的,需要自己重寫Ocelot的中介軟體才能實現。通過Ocelot中介軟體的重寫你可以實現自己的授權邏輯,如果你還有限流的需求,比如說對每個客戶端進行不同的限流策略。比方說,有三個客戶端A,B,C。訪問相同的URL,但是我們要控制A,每分鐘只能訪問10次,B每分鐘能訪問20次,而C不允許訪問。針對這個場景Ocelot卻沒有相關的實現。但是我們可以通過重寫Ocelot中介軟體來實現它。由於篇幅有限,所以今天就不進行介紹了。但是我會抽時間進行相關的實現,並分享給大家。

原始碼

總結

本文先大致介紹一下Ocelot如何整合認證授權,然後通過例項進行了IdentityServer整合的演示,希望能對大家有一定的參考作用。當然文中也提到了,應對複雜的授權以及限流需要自行重寫Ocelot中介軟體進行實現。具體如何實現呢,我會盡快分享給大家。同樣的通過重寫Ocelot中介軟體我們還可以把ocelot.json的配置資訊儲存到資料庫並快取到Redis中!最後,感謝大家的閱讀!