Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(二)
上文已經介紹了Identity Service的實現過程。今天我們繼續,實現一個簡單的Weather API和一個基于Ocelot的API網關。
回顧
《Angular SPA基于Ocelot API網關與IdentityServer4的身份認證與授權(一)》
Weather API
Weather API實現非常簡單,直接用Visual Studio 2019 Community Edition自帶的ASP.NET Core Web Application模板創建就行了,我們的目的不是為了實現Weather API的業務,我們只需要有一個能讓IdentityServer4進行保護的API就行,以便能夠完成我們的各種實驗。
在原有的(也就是Identity Service所在的)解決方案中,新建一個ASP.NET Core Web Application,應用程序模板選擇API,并禁用HTTPS和Docker支持,因為目前不需要,也不要啟用任何Authentication機制,因為這部分功能會由Ocelot配合IdentityServer4實現。在完成創建之后,我們的Weather API就做好了。
現在,設置啟動端口為5000,啟動項目,然后通過curl測試API是否工作正常:
1 | curl http://localhost:5000/weatherforecast | json_pp && echo |
OK,Weather API就成功完成了。
Ocelot API網關
現在我們來創建Ocelot API網關,首先做到能夠通過這個網關來訪問Weather API,然后再加入認證機制,使得Ocelot API網關能夠基于IdentityServer4完成認證。其實這部分實操我已經在《ASP.NET Core中Ocelot的使用:API網關的應用》和《使用Ocelot、IdentityServer4、Spring Cloud Eureka搭建微服務網關:Step by Step(二)》這些文章中介紹過了。為了保證描述的完整性,我還是把這部分工作重新做一次。
搭建網關
新建一個ASP.NET Core Web Application應用程序,模板選擇Empty,去掉HTTPS支持。在項目創建后,向項目添加ocelot.config.json文件,內容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { ??"ReRoutes": [ ????{ ??????"DownstreamPathTemplate": "/weatherforecast", ??????"DownstreamScheme": "http", ??????"DownstreamHostAndPorts": [ ????????{ ??????????"Host": "localhost", ??????????"Port": 5000 ????????} ??????], ??????"UpstreamPathTemplate": "/api/weather", ??????"UpstreamHttpMethod": [ "Get" ] ????} ??] } |
然后,向項目添加Ocelot的NuGet包,修改Program.cs文件,將ocelot.config.json文件添加到應用程序配置系統中:
1 2 3 4 5 6 7 8 9 10 | public static IHostBuilder CreateHostBuilder(string[] args) => ????Host.CreateDefaultBuilder(args) ????????.ConfigureWebHostDefaults(webBuilder => ????????{ ????????????webBuilder.UseStartup<Startup>(); ????????}) ????????.ConfigureAppConfiguration(configBuilder => ????????{ ????????????configBuilder.AddJsonFile("ocelot.configuration.json"); ????????}); |
并且修改Startup.cs文件,加入Ocelot的服務注冊以及Middleware:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public void ConfigureServices(IServiceCollection services) { ????services.AddOcelot(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ????if (env.IsDevelopment()) ????{ ????????app.UseDeveloperExceptionPage(); ????} ? ????app.UseRouting(); ????app.UseOcelot(); ? ????app.UseEndpoints(endpoints => ????{ ????????endpoints.MapGet("/", async context => ????????{ ????????????await context.Response.WriteAsync("Hello World!"); ????????}); ????}); } |
讓API網關偵聽9000端口,同時啟動Weather API和API網關兩個項目,于是我們可以直接通過API網關來訪問Weather API:
1 | curl http://localhost:9000/api/weather | json_pp && echo |
可以看到,我們已經可以直接通過API網關的地址來訪問其下游服務了。
在網關上實現身份認證
接下來的這一步,我們會結合前一篇文章中介紹的Identity Service,在API網關上實現身份認證。在Ocelot API網關項目上,添加IdentityServer4.AccessTokenValidation NuGet包的引用,然后在Startup.cs的ConfigureServices中增加對IdentityServer4的認證支持:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public void ConfigureServices(IServiceCollection services) { ????services.AddOcelot(); ????services.AddAuthentication() ????????.AddIdentityServerAuthentication("AuthKey", options => ????????{ ????????????options.Authority = "http://localhost:7889"; ????????????options.RequireHttpsMetadata = false; ????????}); ????services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin() ???????.AllowAnyMethod() ???????.AllowAnyHeader())); } |
當然我們也添加了CORS的Policy,以便能夠支持跨域訪問,為之后的Angular SPA實現做準備。目前,無需對Configure方法做大的改動,只需要添加app.UseCors(“AllowAll”);這一調用,以允許跨域訪問即可。然后,修改ocelot.config.json文件,在Weather API的ReRoute上增加AuthenticationOptions配置,用以啟用基于IdentityServer4的身份認證:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | { ??"ReRoutes": [ ????{ ??????"DownstreamPathTemplate": "/weatherforecast", ??????"DownstreamScheme": "http", ??????"DownstreamHostAndPorts": [ ????????{ ??????????"Host": "localhost", ??????????"Port": 5000 ????????} ??????], ??????"UpstreamPathTemplate": "/api/weather", ??????"UpstreamHttpMethod": [ "Get" ], ??????"AuthenticationOptions": { ????????"AuthenticationProviderKey": "AuthKey", ????????"AllowedScopes": [] ??????} ????} ??] } |
現在,同時啟動Identity Service、Weather API和Ocelot網關三個項目,然后再用curl調用上面相同的地址,可以發現,服務端已經返回了401,告訴我們沒有認證,無法發起API調用請求:
進一步測試
現在,讓我們寫一個Console App作為客戶端,進行進一步測試。新建一個.NET Core Console App的項目,添加IdentityModel NuGet包,Main方法實現如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | static async Task Main(string[] args) { ????using var client = new HttpClient(); ????var discoResponse = await client.GetDiscoveryDocumentAsync("https://localhost:7890"); ????if (discoResponse.IsError) ????{ ????????Console.WriteLine(discoResponse.Error); ????????return; ????} ? ????var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest ????{ ????????Address = discoResponse.TokenEndpoint, ????????ClientId = "webapi", ????????Scope = "api.weather.full_access", ????????ClientSecret = "mysecret", ????????UserName = "daxnet", ????????Password = "P@ssw0rd123" ????}); ? ????if (tokenResponse.IsError) ????{ ????????Console.WriteLine(tokenResponse.Error); ????????return; ????} ? ????Console.WriteLine(tokenResponse.Json); ????client.SetBearerToken(tokenResponse.AccessToken); ????var response = await client.GetAsync("http://localhost:9000/api/weather"); ????Console.WriteLine(response.IsSuccessStatusCode ? ????????$"{response.StatusCode} {await response.Content.ReadAsStringAsync()}" : ????????response.StatusCode.ToString()); } |
仍然同時啟動Identity Service、Weather API和Ocelot網關三個項目,然后調試這個Console App,可以看到,API調用成功:
Console App也返回了正確的結果:
然后,將上面的access_token復制下來,打開https://jwt.io,粘貼到Encoded文本框,在Decoded文本框中可以看到,Identity相關的信息,包括我們在ApiResource上設定的Claims都被包含在了Access Token上:
?
小結
本文實現了一個實驗性質的Weather API,然后搭建了一個Ocelot API網關,并在網關上結合Identity Service完成了身份認證機制,最后通過一個Console App,了解了一下Access Token。下文開始,我會介紹如何在Angular SPA中做身份認證。
源代碼
訪問以下Github地址以獲取源代碼:
https://github.com/daxnet/identity-demo
總結
以上是生活随笔為你收集整理的Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【翻译】.NET 5 Preview 1
- 下一篇: DotNetCore Web应用程序中的