.Net Core使用Ocelot網關(二) -鑑權認證

前言

上一章已經簡單的介紹了ocelot的使用了,可是網關暴露的接口若是什麼人都能訪問的話安全性就過低啦。因此咱們須要去鑑權和認證。這裏咱們使用identityServer4給咱們的網關來鑑權認證。json

建立Identity服務

咱們建立一個identity的服務來用於令牌的發放和鑑權。下圖是個人項目結構。
20191216163523.png
Api_Gatewat端口:5000
Api_A端口:5001
Api_B端口:5002
IdentityServer端口:5003api

經過nuget添加IdentityServer4的包,也能夠經過程序包管理控制檯執行如下命令Install-Package IdentityServer4安全

添加一個Congif文件。app

using System.Collections.Generic;
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;

namespace IdentityServer
{
    public static class Config
    {
        public static IEnumerable<IdentityResource> GetIdentityResourceResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(), //必需要添加,不然報無效的scope錯誤
            };
        }
        // scopes define the API resources in your system
        public static IEnumerable<ApiResource> GetApiResources()
        {
            //可訪問的API資源(資源名,資源描述)
            return new List<ApiResource>
            {
                new ApiResource("Api_A", "Api_A"),
                new ApiResource("Api_B", "Api_B")
            };
        }

        public static IEnumerable<Client> GetClients()
        { 
            return new List<Client>
            {
                new Client
                {
                    ClientId = "client_a", //訪問客戶端Id,必須惟一
                    //使用客戶端受權模式,客戶端只須要clientid和secrets就能夠訪問對應的api資源。
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "Api_A",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile }
                },
                new  Client
                {
                    ClientId = "client_b",
                    ClientSecrets = new [] { new Secret("secret".Sha256()) },
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    AllowedScopes = { "Api_B",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile }
                }
            };
        }
    }
}

添加兩個API資源,而且添加兩個客戶端分別去訪問不一樣資源。ide

Startup 中的 ConfigureServices 中配置IdentityServer服務。ui

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients());
}

Configure 中把IdentityServer放入http管道中。spa

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseIdentityServer();
}

爲ocelot集成Identity

經過nuget添加IdentityServer4.AccessTokenValidation的包,也能夠經過程序包管理控制檯執行如下命令 Install-Package IdentityServer4.AccessTokenValidationcode

IdentityServer4.AccessTokenValidation - 用於驗證IdentityServer4中的JWT和引用令牌orm

StartupConfigureServices 中分別註冊兩個認證方案 Configure 中配置IdentityServer服務。token

public void ConfigureServices(IServiceCollection services)
{

    services.AddAuthentication()
            .AddJwtBearer("Api_A", i =>
            {
                i.Audience = "Api_A";
                i.Authority = "http://localhost:5003";
                i.RequireHttpsMetadata = false;
            }).AddJwtBearer("Api_B", y =>
            {
                y.Audience = "Api_B";
                y.Authority = "http://localhost:5003";
                y.RequireHttpsMetadata = false;
            });
    services.AddOcelot(new ConfigurationBuilder()
            .AddJsonFile("configuration.json")
            .Build());
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseOcelot();
    app.UseAuthorization();
}

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

{
  "ReRoutes": [
    {
      "UpstreamPathTemplate": "/Api_A/{controller}/{action}",
      "DownstreamPathTemplate": "/api/{controller}/{action}",
      "UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5001
        }

      ],
      "RateLimitOptions": {
        "ClientWhitelist": [ "127.0.0.1" ],
        "EnableRateLimiting": true,
        "Period": "1m",
        "PeriodTimespan": 30,
        "Limit": 5
      },
      "FileCacheOptions": {
        "TtlSeconds": 5,
        "Region": "time"
      },
      "UpstreamHeaderTransform": {
        "demo": "a,b"
      },
      "DownstreamHeaderTransform": {
        "demo": "xxxxxxx",
        "Location": "{DownstreamBaseUrl},{BaseUrl}"
      },
      //受權信息
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Api_A",
        "AllowedScopes": []
      }
    },
    {
      "UpstreamPathTemplate": "/Api_B/{controller}/{action}",
      "DownstreamPathTemplate": "/api/{controller}/{action}",
      "UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",  
          "Port": 5002
        }

      ],
      //受權信息
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Api_B",
        "AllowedScopes": []
      }
    }
  ],
  "QoSOptions": {
    "ExceptionsAllowedBeforeBreaking": 3,
    "DurationOfBreak": 20,
    "TimeoutValue": 5000
  },
  "GlobalConfiguration": {
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false,
      "QuotaExceededMessage": "接口限流!",
      "HttpStatusCode": 200,
      "ClientIdHeader": "ClientId"
    }
  }
}

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

演示效果

咱們爲api_a和api_b分別註冊了認證方案。若是咱們不申請token是會401沒有權限訪問。
20191218152014.png

咱們經過identityServer申請一個的token,並用它訪問api_a和api_b。
20191218154725.png
20191218160205.png
QQ20191218-152516-HD (1).gif
能夠看到咱們申請的token是能夠訪問api_a的,可是不能訪問api_b,由於client_a這個客戶端只有訪問api_a的權利。若是想訪問api_b使用client_b申請token就能夠啦。

總結

簡單爲Ocelot集成了IdentityServer,但願對你們有參考價值。若是文中有錯誤請聯繫我更改。

相關文章
相關標籤/搜索