Ocelot和IdentityServer4初体验
Ocelot是一个用.NET Core实现的开源API网关技术。IdentityServer4是一个基于OpenID Connect和OAuth2.0的针对ASP.NET Core的框架,以中间件的形式存在。OAuth是一种授权机制。系统产生一个短期的token,用来代替密码,供第三方应用使用。
使用Ocelot实现路由功能的初体验:
打开VS2019,新建一个ASP.NET Core空白项目,名为“OcelotDemo”
右键-依赖项-管理NuGet程序包-安装Ocelot
新建一个ASP.NET Core Web Api项目,名为“ApiResource”。自动建立了一个WeatherForecastController.cs文件。本demo直接使用这个文件。更改Properties文件夹中的launchSettings.json文件中的"applicationUrl"为“http://localhost:5001”(只要不是5000就行了,因为5000端口已经被OcelotDemo占用了)
在OcelotDemo项目中,右键添加一个JSON文件,名为ocelot.json。
{ "Routes": [ { "DownstreamPathTemplate": "/weatherforecast", "UpstreamPathTemplate": "/weatherforecast", "UpstreamHttpMethod": [ "GET" ], "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5001 } ] } ], "GlobalConfiguration": {} }
可见,ocelot.json文件包括两个部分:“Routes”和“GlobalConfiguration”。这里要注意,一定是“Routes”而不是“ReRoutes”。"Routes"中包括路由的上下游的信息。“GlobalConfiguration”就是全局配置,比如BaseUrl等。
右键ocelot.json文件,选择“属性”-“始终复制”。
Startup.cs代码:
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddOcelot(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseOcelot().Wait(); } }
Program.cs代码:
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddJsonFile("ocelot.json") .AddEnvironmentVariables(); }) .UseStartup(); }
同时启动ApiResource和OcelotDemo两个项目。在Postman中,我们测试一下路由功能。输入上游地址,可以路由到下游的weatherforecast网页。
使用IdentityServer4进行验证和授权的初体验:
Clients是从IdentityServer中请求token的软件,可以是web/desktop app。Clients需要先在IdentityServer中注册,然后才能去申请token。Client既可以通过身份认证令牌(Identity Token)来验证user身份,也可通过授权令牌(Access Token)来访问服务器端的Resources。
Resources是IdentityServer要保护的资源,比如用户的身份数据(IdentityResource)或者API资源(ApiResource)。每个资源都有一个唯一的名称,Client使用这个唯一的名称来访问资源。
Users使用注册过的Clients访问Resources。
在我们上面的项目中,ApiResource项目就相当于Resources,OcelotDemo项目相当于Clients。那么我们现在就再建立一个IdentityServerDemo。同样也是ASP.NET Core空白项目。添加IdentityServer4的NuGet包。同样也需要先修改launchSettings.json中的applicationUrl,不能为5000端口。并添加一个新的ApiConfiguration.cs文件。
public class ApiConfiguration { public static IEnumerableApiScopes => new List { new ApiScope("ApiResource", "ApiResource") }; public static IEnumerable Clients => new List { new Client { ClientId = "Client", ClientSecrets = {new Secret("secret".Sha256())}, AllowedGrantTypes = GrantTypes.ClientCredentials, AllowedScopes = {"ApiResource"} } }; }
用Postman测试并获取AccessToken。启动IdentityServerDemo项目。注意需要使用POST,x-www-form-urlencoded格式,并输入client_id, client_secret, grant_type对应的参数。在右侧可以见到成功生成了access_token。
通过OcelotDemo访问受保护的ApiResource:
给ApiResource添加验证(受到IdentityServer保护),ApiResource.Controllers.WeatherForecastController.cs中的Get函数中,添加[Authorize]。ApiResource.Startup.cs代码:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddAuthentication("Bearer") .AddJwtBearer(options => { options.Authority = "http://localhost:5002"; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters { ValidateAudience = false }; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAuthentication(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
这个时候再访问ApiResource会显示401 Unauthorized
将OcelotDemo注册到IdentityServerDemo中,在OcelotDemo中添加IdentityServer4.AccessTokenValidation程序包。
OcelotDemo.Startup.cs代码:
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddOcelot(); services.AddAuthentication("Bearer") .AddJwtBearer(options => { options.Authority = "http://localhost:5002"; options.RequireHttpsMetadata = false; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAuthentication(); app.UseOcelot().Wait(); } }
同时启动这三个项目,使用Postman测试。先生成token,然后将access_token的内容复制,输入到Authorization Header中(前面要加Bearer),如下图所示,就可以访问受保护的ApiResource了。
Ps:纯新手,这里面还有很多概念我都不是特别能理解。下面给出了IdentityServer4和Ocelot的官方文档,建议遇到问题首先查查官网文档,因为不同的版本问题,产生的错误和解决的方法也是不一样的。
参考文献:
[1].
[2].http://docs.identityserver.io/en/release/index.html
[3].https://ocelot.readthedocs.io/en/latest/index.html