• 小试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 =>
                {
    
                    //不使用https
                    o.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;
                        }
                    };
                });
                //注入授权Handler
                services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
                services.AddSingleton(permissionRequirement);
            }
        }
    }

    YARP项目实现API聚合appsettings.json

    {
      "urls": "https://*:6001;http://*:6000",
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*",
      "Audience": {
        "Secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
        "Issuer": "gsw",
        "Audience": "everone"
      },
      //实现api聚合
      "ReverseProxy": {
        "Routes": [
          //业务服务webapi01
          {
            "RouteId": "webapi01",
            "ClusterId": "webapi01_cluster",
            "AuthorizationPolicy": "Permission",
            "Match": {
              "Path": "/webapi01/{**catch-all}"
            }
          },
          //业务服务webapi02
          {
            "RouteId": "webapi02",
            "ClusterId": "webapi02_cluster",
            "AuthorizationPolicy": "Permission",
            "Match": {
    
              "Path": "/webapi02/{**catch-all}"
            }
          },
          //验证服务
          {
            "RouteId": "authservice",
            "ClusterId": "auth_cluster",
            "Match": {
              "Path": "/auth/{**catch-all}"
            }
          }
        ],
        "Clusters": {
          //业务服务webapi01
          "webapi01_cluster": {
            "Destinations": {
              "webapi01_cluster/destination": {
                "Address": "https://localhost:7001/"
              }
            }
          },
          //业务服务webapi02
          "webapi02_cluster": {
            "Destinations": {
              "webapi02_cluster/destination": {
                "Address": "https://localhost:8001/"
              }
            }
          },
          //验证服务
          "auth_cluster": {
            "Destinations": {
              "auth_cluster/destination": {
                "Address": "https://localhost:5001/"
              }
            }
          }
        }
      }
    }

    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

      想要更快更方便的了解相关知识,可以关注微信公众号 
     

     

     
  • 相关阅读:
    ApplicationContext
    消息队列种类
    Zookeeper的功能以及工作原理
    java多线程(1)模式 不可变对象
    dubbo容错,负载均衡,协议
    dubbo的底层原理
    消息事务处理
    多线程循环打印 abc
    Spring 事务管理
    文件上传和下载
  • 原文地址:https://www.cnblogs.com/axzxs2001/p/15859092.html
Copyright © 2020-2023  润新知