使用JWT令牌的编码值进行NGINX速率限制

我对NGINX速率限制有一个问题。

是否可以根据JWT令牌的解码值进行速率限制?文档中没有这样的信息。

或者,即使通过创建纯自定义变量(使用LuaJIT)来执行速率限制并将其分配给我的已解码JWT的值也可以执行该作业。问题在于,limit_req 模块似乎在请求到达luaJIT阶段之前就会执行,所以为时已晚!

欢迎提出解决方案。

点赞
用户1189800
用户1189800

Nginx 的 JWT 认证

nginx-jwt 是一个 Lua 脚本,为 Nginx 服务器(运行 HttpLuaModule)提供了支持,允许您使用 Nginx 作为反向代理,前置现有的 HTTP 服务并使用受信任的 JSON Web Token(JWT)在 Authorization 请求标头中对其进行保护(身份验证/授权),而无需或只需对后端服务进行少量更改。

重要提示:nginx-jwt 是一个 Lua 脚本,旨在运行在安装了 HttpLuaModule 的 Nginx 服务器上。但是,最终它的依赖项需要 OpenResty Nginx 发行版中可用的组件。因此,建议您使用 OpenResty 作为 Nginx 服务器,本说明假定情况如此。

配置

目前,nginx-jwt 仅支持对称密钥(alg = hs256),因此您需要使用下面的共享 JWT 密钥配置服务器。

  1. 在 Nginx 主机上导出 JWT_SECRET 环境变量,将其设置为您的 JWT 密钥相等。然后将其公开给 Nginx 服务器:
# nginx.conf:

env JWT_SECRET;
  1. 如果您的 JWT 密钥是 Base64(URL-safe)编码,请在 Nginx 主机上导出 JWT_SECRET_IS_BASE64_ENCODED 环境变量,将其设置为 true。然后将其公开给 Nginx 服务器:
# nginx.conf:

env JWT_SECRET_IS_BASE64_ENCODED;

JWT Auth for Nginx

2020-12-02 07:05:26
用户14475852
用户14475852

如您所知,速率限制是通过唯一的 IP 地址进行应用的,为了达到最佳效果,您应使用独特的 JWT 值或令牌进行速率限制。

您可以采用以下任何一种方法:

  1. 方法

您可以直接在 limit_req_zone 中使用 jwt 令牌。

http {
    ...
    limit_req_zone $http_authorization zone=req_zone:10m rate=5r/s;
}

conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    if ($http_authorization = "") {
       return 403;
    }

    location /jwt {
        limit_req zone=req_zone burst=10 nodelay;

        return 200 $http_authorization;
    }
    ...
}
  1. 方法

您可以在前端中通过请求标头发送解码后的 jwt 值,如 http_x_jwt_decode_value,然后您可以在 limit_req_zone 中使用它。

http {
    ...
    limit_req_zone $http_x_jwt_decode_value zone=req_zone:10m rate=5r/s;
}

conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    if ($http_x_jwt_decode_value = "") {
       return 403;
    }

    location /jwt {
        limit_req zone=req_zone burst=10 nodelay;

        return 200 $http_x_jwt_decode_value;
    }
    ...
}
  1. 方法

您可以通过 njs JavaScript 模块、Perl 模块或 Lua 模块在 Nginx 中解码 jwt 令牌并将其分配给变量,然后使用该变量进行速率限制。

描述: 这里我只是解码了 jwt 值并检查它是否为空,您可以使用它来处理 jwt 解码值。

jwt_example.js

function jwt(data) {
  var parts = data.split('.').slice(0,2)
    .map(v=>String.bytesFrom(v, 'base64url'))
    .map(JSON.parse);
  return { headers:parts[0], payload: parts[1] };
}

function jwt_payload_sub(r) {
  return jwt(r.headersIn.Authorization.slice(7)).payload.sub;
}

export default {jwt_payload_sub}

nginx.conf


# njs 模块
load_module modules/ngx_http_js_module.so;

http {
    ...
    include /etc/nginx/conf.d/*.conf;

    js_import main from jwt_example.js;

    js_set $jwt_payload_sub main.jwt_payload_sub;

    limit_req_zone $jwt_payload_sub zone=req_zone:10m rate=5r/s;
}

conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    if ($jwt_payload_sub = "") {
       return 403;
    }

    location /jwt {
        limit_req zone=req_zone burst=10 nodelay;

        return 200 $jwt_payload_sub;
    }
    ...
}
2020-12-03 06:37:22