net 6 基于网关的鉴权授权

网关其实也是一个net core 应用程序,和其他鉴权方式一下,所以我们在prgram 的文件直接写  鉴权方式

#region jwt校验  HS
JWTTokenOptions tokenOptions = new JWTTokenOptions();
builder.Configuration.Bind("JWTTokenOptions", tokenOptions);
string authenticationProviderKey = "UserGatewayKey";

builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)//Bearer Scheme
.AddJwtBearer(authenticationProviderKey, options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        //JWT有一些默认的属性,就是给鉴权时就可以筛选了
        ValidateIssuer = true,//是否验证Issuer
        ValidateAudience = true,//是否验证Audience
        ValidateLifetime = true,//是否验证失效时间---默认还添加了300s后才过期
        ClockSkew = TimeSpan.FromSeconds(0),//token过期后立马过期
        ValidateIssuerSigningKey = true,//是否验证SecurityKey

        ValidAudience = tokenOptions.Audience,//Audience,需要跟前面签发jwt的设置一致
        ValidIssuer = tokenOptions.Issuer,//Issuer,这两项和前面签发jwt的设置一致
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.SecurityKey)),//拿到SecurityKey
    };
});
#endregion


  
    配置文件如下

//*****************************超时+限流+熔断+降级+Consul+Polly********************************
{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量
      "DownstreamScheme": "http",
      "UpstreamPathTemplate": "/T/{url}", //网关地址--url变量
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "UseServiceDiscovery": true,
      "ServiceName": "UserWebAPIService", //consul服务名称
      "LoadBalancerOptions": {
        "Type": "RoundRobin" //轮询      LeastConnection-最少连接数的服务器   NoLoadBalance不负载均衡
      },
      "RateLimitOptions": {
        "ClientWhitelist": [ "1111", "2222" ], //白名单 ClientId 区分大小写
        "EnableRateLimiting": true,
        "Period": "5m", //1s, 5m, 1h, 1d
        "PeriodTimespan": 30, //多少秒之后客户端可以重试
        "Limit": 5 //统计时间段内允许的最大请求数量
      },
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "UserGatewayKey",
        "AllowedScopes": [ "UserWebAPIService", "UserMinimalAPIService" ]
      },
      "RouteClaimsRequirement": {
        "Role": "Assistant"
      },
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求
        "DurationOfBreak": 10000, // 熔断的时间,单位为ms
        "TimeoutValue": 2000 //单位ms 如果下游请求的处理时间超过多少则自如将请求设置为超时 默认90秒
      },
      "FileCacheOptions": {
        "TtlSeconds": 15,
        "Region": "UserCache" //可以调用Api清理
      }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://127.0.0.1:6299", //网关对外地址
    "ServiceDiscoveryProvider": {
      "Host": "127.0.0.1",
      "Port": 8500,
      "Type": "Consul" //由Consul提供服务发现
    },
    "RateLimitOptions": {
      "QuotaExceededMessage": "Too many requests, maybe later? 11", // 当请求过载被截断时返回的消息
      "HttpStatusCode": 666, // 当请求过载被截断时返回的http status
      "ClientIdHeader": "client_id" // 用来识别客户端的请求头,默认是 ClientId
    }
  }
}

 

UserGatewayKey  是指定一个key  来管理网关的配置文件的路由,来标识 哪些路由是需要鉴权授权的。
AllowedScopes 用来做资源区分的,在用户信息里面指定这个claim 里面scopes 

在生成token 的地方把值写入进去
      private string IssueToken(CurrentUserModel userModel, int second = 600)
        {
            var claims = new[]
            {
                   new Claim("scope", "UserWebAPIService"),//为了微服务的Scope,必须小写
                   new Claim(ClaimTypes.Name, userModel.Name),
                   new Claim("EMail", userModel.EMail),
                   new Claim("Account", userModel.Account),
                   new Claim("Age", userModel.Age.ToString()),
                   new Claim("Id", userModel.Id.ToString()),
                   new Claim("Mobile", userModel.Mobile),
                   new Claim(ClaimTypes.Role,userModel.Role),
                   new Claim("Role", "Assistant"),//这个不能默认角色授权,动态角色授权
                   new Claim("Sex", userModel.Sex.ToString())//各种信息拼装
            };
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this._JWTTokenOptions.SecurityKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            /**
             * Claims (Payload)
                Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段,下面节选一些字段:
                iss: The issuer of the token,token 是给谁的
                sub: The subject of the token,token 主题
                exp: Expiration Time。 token 过期时间,Unix 时间戳格式
                iat: Issued At。 token 创建时间, Unix 时间戳格式
                jti: JWT ID。针对当前 token 的唯一标识
                除了规定的字段外,可以包含其他任何 JSON 兼容的字段。
             * */
            var token = new JwtSecurityToken(
                issuer: this._JWTTokenOptions.Issuer,
                audience: this._JWTTokenOptions.Audience,
                claims: claims,
                expires: DateTime.Now.AddSeconds(second),//10分钟有效期
                notBefore: DateTime.Now,//立即生效  DateTime.Now.AddMilliseconds(30),//30s后有效
                signingCredentials: creds);
            string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
            return returnToken;
        }

 



真实开发时,我们不可能把所有鉴权的规则都放在网关去做,网关不会太细仔的,网关层只检查token 有效性, 更多细则应该在实例层去做
posted @ 2022-02-08 14:45  非著名架构师  阅读(900)  评论(0编辑  收藏  举报