Ocelot.JwtAuthorize:一个基于网关的Jwt验证包

在现代的分布式系统架构中,API网关扮演着至关重要的角色,它作为系统的统一入口,负责请求的路由、负载均衡、安全验证等功能。而JWT(JSON Web Token)作为一种轻量级的身份验证和授权机制,被广泛应用于前后端分离的项目中。Ocelot.JwtAuthorize 是一个专门为Ocelot网关设计的JWT验证包,它能够帮助开发者轻松地在网关层面实现JWT验证,提高系统的安全性和可维护性。本文将详细介绍 Ocelot.JwtAuthorize 的使用方法、常见实践和最佳实践。

目录#

  1. Ocelot简介
  2. JWT简介
  3. Ocelot.JwtAuthorize概述
  4. 安装和配置
    1. 安装包
    2. 配置Ocelot
    3. 配置JWT验证参数
  5. 使用示例
    1. 创建JWT令牌
    2. 在Ocelot中启用JWT验证
  6. 常见实践
    1. 基于角色的访问控制
    2. 自定义验证逻辑
  7. 最佳实践
    1. 密钥管理
    2. 刷新令牌机制
  8. 参考资料

Ocelot简介#

Ocelot是一个开源的.NET Core API网关,它提供了路由、负载均衡、限流、熔断等一系列功能,能够帮助开发者快速构建高性能、可扩展的API网关。Ocelot的配置非常灵活,支持通过JSON文件或代码的方式进行配置,同时还提供了丰富的中间件扩展机制,方便开发者根据自己的需求进行定制。

JWT简介#

JWT是一种基于JSON的开放标准(RFC 7519),用于在网络应用之间安全地传输声明。JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。头部包含了令牌的类型和使用的签名算法,载荷包含了一些声明信息,如用户ID、角色等,签名用于验证令牌的真实性和完整性。JWT的优点在于它是无状态的,不需要在服务器端存储会话信息,因此非常适合用于分布式系统。

Ocelot.JwtAuthorize概述#

Ocelot.JwtAuthorize 是一个基于Ocelot的JWT验证中间件,它能够在网关层面拦截请求,验证请求中的JWT令牌是否有效。如果令牌无效,网关将直接返回401 Unauthorized响应,阻止请求继续转发到后端服务。Ocelot.JwtAuthorize 支持多种验证方式,如签名验证、过期时间验证等,同时还支持自定义验证逻辑,方便开发者根据自己的需求进行定制。

安装和配置#

安装包#

首先,我们需要在Ocelot项目中安装 Ocelot.JwtAuthorize 包。可以通过NuGet包管理器或命令行工具进行安装:

dotnet add package Ocelot.JwtAuthorize

配置Ocelot#

Startup.cs 文件中,我们需要配置Ocelot并启用 Ocelot.JwtAuthorize 中间件。示例代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.JwtAuthorize;
 
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
 
    public IConfiguration Configuration { get; }
 
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOcelot()
                .AddJwtAuthorize();
    }
 
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
 
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
 
        app.UseOcelot().Wait();
    }
}

配置JWT验证参数#

ocelot.json 配置文件中,我们需要配置JWT验证的参数。示例配置如下:

{
    "ReRoutes": [
        {
            "DownstreamPathTemplate": "/api/{everything}",
            "DownstreamScheme": "http",
            "DownstreamHostAndPorts": [
                {
                    "Host": "localhost",
                    "Port": 5001
                }
            ],
            "UpstreamPathTemplate": "/{everything}",
            "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
            "AuthenticationOptions": {
                "AuthenticationProviderKey": "JwtBearer",
                "AllowedScopes": []
            }
        }
    ],
    "GlobalConfiguration": {
        "BaseUrl": "http://localhost:5000",
        "JwtOptions": {
            "Audience": "api",
            "Issuer": "your_issuer",
            "Key": "your_secret_key",
            "RequireHttpsMetadata": false
        }
    }
}

在上述配置中,AuthenticationOptions 用于指定需要进行身份验证的路由,JwtOptions 用于配置JWT的验证参数,如受众(Audience)、颁发者(Issuer)和密钥(Key)等。

使用示例#

创建JWT令牌#

下面是一个简单的示例代码,用于创建JWT令牌:

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
 
public class JwtHelper
{
    public static string GenerateToken(string issuer, string audience, string secretKey, string username, string role)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(secretKey);
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.Name, username),
                new Claim(ClaimTypes.Role, role)
            }),
            Issuer = issuer,
            Audience = audience,
            Expires = DateTime.UtcNow.AddHours(1),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }
}

在Ocelot中启用JWT验证#

将生成的JWT令牌添加到请求的 Authorization 头部,格式为 Bearer {token}。Ocelot会自动拦截请求,并验证令牌的有效性。

常见实践#

基于角色的访问控制#

在实际应用中,我们通常需要根据用户的角色来控制对API的访问。可以在JWT的载荷中添加角色信息,并在Ocelot的配置文件中配置需要的角色。示例配置如下:

{
    "ReRoutes": [
        {
            "DownstreamPathTemplate": "/api/admin/{everything}",
            "DownstreamScheme": "http",
            "DownstreamHostAndPorts": [
                {
                    "Host": "localhost",
                    "Port": 5001
                }
            ],
            "UpstreamPathTemplate": "/admin/{everything}",
            "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
            "AuthenticationOptions": {
                "AuthenticationProviderKey": "JwtBearer",
                "AllowedScopes": [],
                "AllowedRoles": [ "Admin" ]
            }
        }
    ]
}

在上述配置中,只有拥有 Admin 角色的用户才能访问 /admin 开头的API。

自定义验证逻辑#

如果默认的验证逻辑无法满足需求,我们可以自定义验证逻辑。可以通过实现 IJwtAuthorizeValidator 接口来实现自定义验证。示例代码如下:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.JwtAuthorize;
 
public class CustomJwtValidator : IJwtAuthorizeValidator
{
    public Task<bool> ValidateAsync(HttpContext context, string token)
    {
        // 自定义验证逻辑
        return Task.FromResult(true);
    }
}

然后在 Startup.cs 中注册自定义验证器:

services.AddOcelot()
        .AddJwtAuthorize(options =>
        {
            options.Validator = new CustomJwtValidator();
        });

最佳实践#

密钥管理#

JWT的签名密钥是保证令牌安全性的关键。建议将密钥存储在安全的地方,如环境变量或配置中心。避免将密钥硬编码在代码中,以防止密钥泄露。

刷新令牌机制#

为了提高用户体验和安全性,可以实现刷新令牌机制。当访问令牌过期时,用户可以使用刷新令牌获取新的访问令牌,而不需要重新登录。实现刷新令牌机制可以参考相关的JWT实现文档。

参考资料#

通过以上的介绍,相信你已经对 Ocelot.JwtAuthorize 有了更深入的了解。希望本文能够帮助你在项目中更好地使用 Ocelot.JwtAuthorize 实现JWT验证。