查看原文
其他

.NET 5 微服务网关 Ocelot 加入IdentityServer 4 鉴权

DotNet 2022-07-19

↓推荐关注↓

相关文章
《.NET 5 中使用 Consul+Ocelot+Polly》
《.NET 5 中使用-网关 Ocelot+Consul》
《.NET 5 中使用 Consul+Ocelot+Polly缓存、限流、熔断、降级》
一、简介

描述:微服务网关中,需要对访问的接口进行身份校验后再转发请求,网关中鉴权的方式有很多种,这里介绍的是常用的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

转自:包子wxl

链接:cnblogs.com/wei325/p/15415766.html


- EOF -

推荐阅读  点击标题可跳转
.NET Core 中如何调试死锁 ? .NET Core 中如何有效屏蔽重复提交 
PublishFolderCleaner 让.NET 应用发布文件夹更加整洁

看完本文有收获?请转发分享给更多人

推荐关注「DotNet」,提升.Net技能 

点赞和在看就是最大的支持❤️

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存