Ocelot之结合IdentityServer4认证二

Ocelot之结合IdentityServer4认证二

前言

上章节介绍了Ocelot之结合IdentityServer4认证一,Ocelot网关仅仅是提供路由服务,这节介绍在网关中进行认证。

环境

Win10+VS2022 +.NET5.0 + Ocelot17.0.0.0 + Consul 1.6.1.1+IDS4

项目实现

在上节“Ocelot之结合IdentityServer4认证一”的项目实现上继续改造。

 

 

 

1.1 创建IDS4项目

IDS4项目上节已经创建,这里为了阅读方便再显示下创建过程。

1. 创建项目

dotnet CLI快速安装模板Identityserver模板

dotnet new -i IdentityServer4.Templates 

 

创建IdentityServery 项目

dotnet new is4empty -n IdentityServer_ResourceOwnerPasswordCredentials  

 

2.引用IdentityServer4依赖

3.修改端口

Properties\launchSettings.json文件中更改它。

 

这里修改为:

 "applicationUrl": "https://localhost:5001;http://localhost:5000"

 

4.定义API接口的活动范围API Scope

API 是系统中要保护的资源。资源定义可以通过多种方式加载。模板已经创建了 Config.cs。打开它,将代码更新为如下所示:

 public static IEnumerable<ApiScope> ApiScopes =>

            new ApiScope[]

            { new ApiScope("Yak.Ocelot.Api", "My API")};

 

 

5.添加用户

就像基于内存存储的资源(即范围 Scopes)和客户端一样,对于用户也可以这样做。

TestUser类型表示一个测试用户及其身份信息。 Config.cs文件中添加以下代码以创建用户:

 public static List<TestUser> GetUsers()

        {

            return new List<TestUser>

            {

                new TestUser

                {

                    SubjectId = "1",

                    Username = "alice",

                    Password = "password"

                },

                new TestUser

                {

                    SubjectId = "2",

                    Username = "bob",

                    Password = "password"

                },

                new TestUser

                {

                    SubjectId = "3",

                    Username = "yak",

                    Password = "yakpassword"

                }

            };

        }

 

             

5. 添加IdentityResources

 public static IEnumerable<IdentityResource> GetIdentityResources()

        {

            return new IdentityResource[]

            {

                new IdentityResources.OpenId(),//未添加导致scope错误

                new IdentityResources.Profile()

            };

        }

 

7.配置身份服务器

在Startup文件中配置身份服务器,加载资源和客户端,然后将测试用户注册到 IdentityServer中。代码如下:

 public void ConfigureServices(IServiceCollection services)

        {

            var builder = services.AddIdentityServer()

                .AddInMemoryIdentityResources(Config.GetIdentityResources())

                .AddInMemoryApiScopes(Config.ApiScopes)

                .AddInMemoryClients(Config.GetClients())

                .AddTestUsers(Config.GetUsers());

            builder.AddDeveloperSigningCredential();

        }

 

 

 

AddTestUsers扩展方法在背后做了以下几件事:

(1)为资源所有者密码授权添加支持

(2)添加对用户相关服务的支持,这服务通常为登录 UI 所使用

(3)为基于测试用户的身份信息服务添加支持

 

7.添加客户端定义

可以通过修改AllowedGrantTypes属性简单地添加对已有客户端授权类型的支持。

通常要为资源所有者用例创建独立的客户端,添加以下代码到你配置中的客户端定义中

public static IEnumerable<Client> GetClients()

        {

            return new List<Client>

            {

                // resource owner password grant client

                new Client

                {

                    ClientId = "yakclient",

                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

 

                    ClientSecrets =

                    {

                        new Secret("yaksecret".Sha256())

                    },

                    AllowedScopes = { "Yak.Ocelot.Api", IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile }//需要额外添加

                }

            };

        }

 

 

 

1.2 修改接口服务

1. 在接口控制器上去掉认证特性。

  //[Authorize]

   [ApiController]

    [Route("[controller]")]

public class WeatherForecastController : ControllerBase

............

 

2. 删除Microsoft.AspNetCore.Authentication.JwtBearer依赖

3. 修改Startup文件,删除认证代码。

  public void ConfigureServices(IServiceCollection services)

        {

            services.AddSingleton(Configuration.GetSection("Consul").Get<ConsulOption>());

            services.AddControllers();

        }

 

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ConsulOption consulOption)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }

            // 注册

            app.RegisterConsul(lifetime, consulOption);

            app.UseRouting();

 

            app.UseAuthorization();

 

            app.UseEndpoints(endpoints =>

            {

                endpoints.MapControllers();

            });

        }

 

1.3 修改网关

1.添加Microsoft.AspNetCore.Authentication.JwtBearer依赖

添加后所有的依赖有:

 

 <ItemGroup>

  <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0" />

    <PackageReference Include="Ocelot" Version="17.0.0" />

    <PackageReference Include="Ocelot.Cache.CacheManager" Version="17.0.0" />

    <PackageReference Include="Ocelot.Provider.Consul" Version="17.0.0" />

    <PackageReference Include="Ocelot.Provider.Polly" Version="17.0.0" />

  </ItemGroup>

 

4. 修改ocelot配置

{

  "Routes": [

    {

      "DownstreamPathTemplate": "/WeatherForecast",

      "DownstreamScheme": "http",

      "ServiceName": "service-a",

      "UseServiceDiscovery": true,

      "UpstreamPathTemplate": "/Weather",

      "UpstreamHttpMethod": [ "Get" ],

      "LoadBalancerOptions": {

        "Type": "RoundRobin"

      }, //熔断器Polly

      "QoSOptions": {

        "ExceptionsAllowedBeforeBreaking": 3, //打开断路器之前允许的多少个异常请求

        "DurationOfBreak": 60000, // 熔断时间

        "TimeoutValue": 1000 //请求超时时间(毫秒)

      },

      //鉴权

      "AuthenticationOptions": {

        "AuthenticationProviderKey": "Gatewaykey",

        "AllowedScopes": [ "Yak.Ocelot.Api" ]

      }

    }

  ],

  "GlobalConfiguration": {

    "BaseUrl": "http://localhost:5000"

  }

}

添加鉴权配置:

5. 修改Startup文件,添加认证代码。

public void ConfigureServices(IServiceCollection services)

        {

            var identityBuilder = services.AddAuthentication();

            IdentityServerConfig identityServerConfig = new IdentityServerConfig()

            IdentityModelEventSource.ShowPII = true;

            var authenticationProviderKey = "Gatewaykey";

            services.AddAuthentication().AddJwtBearer(authenticationProviderKey, x =>

            {

                x.Authority = "http://localhost:8000";

                x.RequireHttpsMetadata = false;

                x.TokenValidationParameters = new TokenValidationParameters

                {

                    ValidateAudience = false

                };

            });

 

            services.AddControllers();

            services.AddOcelot(Configuration).AddConsul().AddPolly();

        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }

            

            app.UseRouting();

            app.UseAuthentication();//先鉴权,没有鉴权,授权是没有意义的

            app.UseAuthorization();//后授权

            app.UseEndpoints(endpoints =>

            {

                endpoints.MapGet("/", async context =>

                {

                    await context.Response.WriteAsync("我是Ocelot网关!");

                });

            });

            

            app.UseOcelot();

        }

 

1.4 启动Consul

这里是Win10系统,下载相应的Consul后,在文件夹下创建启动BAT文件用于启动Consul,双击启动。

1.5 服务发现

启动Yak.Ocelot.Api”项目,查看到服务已经注册到Consul中。

 

 

 

 

 

1.6 调试

1. 启动网关服务

运行网关项目Yak.Ocelot.Gateway”。

 

 

 

2. 启动接口服务

运行接口项目Yak.Ocelot.Api”。

 

3. Token

启动IDS4服务获取Token,地址:http://localhost:8000/connect/token

参数:

grant_type:password

client_id:yakclient

client_secret:yaksecret

username:yak

password:yakpassword

 

 

 

 

 

 

4. 通过网关访问接口服务

通过网关地址http://localhost:5000/Weather

访问WebAPI天气接口服务,返回401未认证。

 

 

 

添加Token认证后访问

 参数:

Authorization :   Bearer token

 

 

 

 

 

 

总结

这节例子是在上节的例子进行改造,上节的网关仅仅提供了路由,这节介绍网关结合IDS4提供认证。

首先在鉴权服务中心请求获取Token,拿到Token后去请求实例服务上的接口。鉴权中心和服务实例并没有进行交互。在第一次请求到达服务实例的时候,服务实例会去鉴权中心请求拿到公钥。之后就不在需要和鉴权中心进行交互,除非服务实例重新启动。

既然是微服务架构,所以鉴权也统一走网关,不然每一个服务实例都要写一套鉴权的代码。因为走网关鉴权,所以所有的api都要授权才能访问。

 

鸣谢

https://cloud.tencent.com/developer/article/1174014

https://blog.csdn.net/qin_yu_2010/article/details/83120215

https://www.cnblogs.com/zhengwei-cq/p/12856267.html

https://www.cnblogs.com/zhangnever/p/13198176.html

源码

https://github.com/yandaniugithub/NETCore

 

posted @ 2022-04-10 22:19  春光牛牛  阅读(161)  评论(0编辑  收藏  举报