.Net Core使用Ocelot网关(二) -鉴权认证

ε祈祈猫儿з 提交于 2020-08-17 18:39:43

前言

上一章已经简单的介绍了ocelot的使用了,但是网关暴露的接口如果什么人都能访问的话安全性就太低啦。所以我们需要去鉴权和认证。这里我们使用identityServer4给我们的网关来鉴权认证。

创建Identity服务

我们创建一个identity的服务来用于令牌的发放和鉴权。下图是我的项目结构。
20191216163523.png
Api_Gatewat端口:5000
Api_A端口:5001
Api_B端口:5002
IdentityServer端口:5003




通过nuget添加IdentityServer4的包,也可以通过程序包管理控制台执行以下命令Install-Package IdentityServer4

添加一个Congif文件。

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资源,并且添加两个客户端分别去访问不同资源。

Startup 中的 ConfigureServices 中配置IdentityServer服务。

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

Configure 中把IdentityServer放入http管道中。

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

为ocelot集成Identity

通过nuget添加IdentityServer4.AccessTokenValidation的包,也可以通过程序包管理控制台执行以下命令 Install-Package IdentityServer4.AccessTokenValidation

IdentityServer4.AccessTokenValidation - 用于验证IdentityServer4中的JWT和引用令牌

StartupConfigureServices 中分别注册两个认证方案 Configure 中配置IdentityServer服务。

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,希望对大家有参考价值。如果文中有错误请联系我更改。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!