小试YARP
.net core下,一個輕量組反向代理庫,由微軟發起。
做了一個簡單的帶驗證的反向代理,應用結構如上圖,一個驗證服務,兩個業務服務和一個YARP服務。
源碼
https://github.com/axzxs2001/Asp.NetCoreExperiment/tree/master/Asp.NetCoreExperiment/YARP
YARP的Starup.cs如下,主要是用來添加YARP組件和添加權限組件部分。
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System.IdentityModel.Tokens.Jwt; using Microsoft.IdentityModel.Tokens; using Microsoft.Extensions.Hosting; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; using System.Text; using System;namespace YARPDemo01 {public class Startup{public IConfiguration Configuration { get; }public Startup(IConfiguration configuration){Configuration = configuration;}public void ConfigureServices(IServiceCollection services){AddAuth(services);services.AddReverseProxy().LoadFromConfig(Configuration.GetSection("ReverseProxy"));}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseAuthentication();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapReverseProxy();});}void AddAuth(IServiceCollection services){//讀取配置文件var audienceConfig = Configuration.GetSection("Audience");var symmetricKeyAsBase64 = audienceConfig["Secret"];var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);var signingKey = new SymmetricSecurityKey(keyByteArray);var tokenValidationParameters = new TokenValidationParameters{ValidateIssuerSigningKey = true,IssuerSigningKey = signingKey,ValidateIssuer = true,ValidIssuer = audienceConfig["Issuer"],ValidateAudience = true,ValidAudience = audienceConfig["Audience"],ValidateLifetime = true,ClockSkew = TimeSpan.Zero,RequireExpirationTime = true,};var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);//這個集合模擬用戶權限表,可從數據庫中查詢出來var permission = new List<Permission> {new Permission { Url="/webapi01/test1", Name="admin"},new Permission { Url="/webapi01/test3", Name="admin"},new Permission { Url="/webapi02/test2", Name="admin"},new Permission { Url="/webapi02/test4", Name="admin"},};//如果第三個參數,是ClaimTypes.Role,上面集合的每個元素的Name為角色名稱,如果ClaimTypes.Name,即上面集合的每個元素的Name為用戶名var permissionRequirement = new PermissionRequirement("/api/denied", permission,ClaimTypes.Role,audienceConfig["Issuer"],audienceConfig["Audience"],signingCredentials,expiration: TimeSpan.FromSeconds(1000000)//設置Token過期時間);services.AddAuthorization(options =>{options.AddPolicy("Permission", policy => policy.AddRequirements(permissionRequirement));}).AddAuthentication(options =>{options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o =>{//不使用httpso.RequireHttpsMetadata = false;o.TokenValidationParameters = tokenValidationParameters;o.Events = new JwtBearerEvents{OnTokenValidated = context =>{if (context.Request.Path.Value.ToString() == "/api/logout"){var token = ((context as TokenValidatedContext).SecurityToken as JwtSecurityToken).RawData;}return Task.CompletedTask;}};});//注入授權Handlerservices.AddSingleton<IAuthorizationHandler, PermissionHandler>();services.AddSingleton(permissionRequirement);}} }YARP項目實現API聚合appsettings.json
Auth項目實現登錄簽名部分
using System; using?System.IdentityModel.Tokens.Jwt; using?System.Security.Claims; namespace AuthenticationAuthorization_Token {public class JwtToken{/// <summary>/// 獲取基于JWT的Token/// </summary>/// <param name="username"></param>/// <returns></returns>public static dynamic BuildJwtToken(Claim[] claims, PermissionRequirement permissionRequirement){var now = DateTime.UtcNow;var jwt = new JwtSecurityToken(issuer: permissionRequirement.Issuer,audience: permissionRequirement.Audience,claims: claims,notBefore: now,expires: now.Add(permissionRequirement.Expiration),signingCredentials: permissionRequirement.SigningCredentials);var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);var response = new{Status = true,access_token = encodedJwt,expires_in = permissionRequirement.Expiration.TotalMilliseconds,token_type = "Bearer"};return response;}} }看結果:
首先登錄獲取token,用戶名gsw,密碼111111
訪問webapi01
訪問webapi02
總結
- 上一篇: 如何使用 C# 中的 HashSet
- 下一篇: Entity Framework Cor