跳转至

teslagov-jwt: 使用 JWT 保护您的 NGINX 位置

安装

您可以在任何基于 RHEL 的发行版中安装此模块,包括但不限于:

  • RedHat Enterprise Linux 7、8、9 和 10
  • CentOS 7、8、9
  • AlmaLinux 8、9
  • Rocky Linux 8、9
  • Amazon Linux 2 和 Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-teslagov-jwt
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-teslagov-jwt

通过在 /etc/nginx/nginx.conf 顶部添加以下内容来启用模块:

load_module modules/ngx_http_auth_jwt_module.so;

本文档描述了 nginx-module-teslagov-jwt v2.4.0,于 2025 年 9 月 17 日发布。


这是一个 NGINX 模块,用于检查有效的 JWT 并代理到上游服务器或重定向到登录页面。它支持额外的功能,例如从 JWT 中提取声明并将其放置在请求/响应头中。

v2 的重大变化

v2 分支现已合并到 master,包括重大变化。有关详细信息,请参见初始 v2 发布。

指令

此模块需要几个新的 nginx.conf 指令,可以在 httpserverlocation 级别指定。有关更多信息,请参见 示例 NGINX 配置文件

指令 描述
auth_jwt_key 用于解码/验证 JWT 的密钥,以 binhex 格式 -- 见下文。
auth_jwt_redirect 设置为 "on" 以在身份验证失败时重定向到 auth_jwt_loginurl
auth_jwt_loginurl 如果启用 auth_jwt_redirect 且身份验证失败,则重定向到的 URL。
auth_jwt_enabled 设置为 "on" 以启用 JWT 检查。
auth_jwt_algorithm 要使用的算法。可选值:HS256、HS384、HS512、RS256、RS384、RS512
auth_jwt_location 指示 JWT 在请求中的位置 -- 见下文。
auth_jwt_validate_sub 设置为 "on" 以验证 JWT 中的 sub 声明(例如用户 ID)。
auth_jwt_extract_var_claims 设置为要从 JWT 中提取的声明的以空格分隔的列表,并作为 NGINX 变量提供。这些变量可以通过例如 $jwt_claim_sub 访问。
auth_jwt_extract_request_claims 设置为要从 JWT 中提取的声明的以空格分隔的列表,并设置为请求头。这些变量可以通过例如 $http_jwt_sub 访问。
auth_jwt_extract_response_claims 设置为要从 JWT 中提取的声明的以空格分隔的列表,并设置为响应头。这些变量可以通过例如 $sent_http_jwt_sub 访问。
auth_jwt_use_keyfile 设置为 "on" 以从文件中读取密钥,而不是从 auth_jwt_key 指令中读取。
auth_jwt_keyfile_path 设置为启用 auth_jwt_use_keyfile 时应读取密钥的路径。

算法

默认算法为 HS256,用于对称密钥验证。当使用 HS* 算法之一时,auth_jwt_key 的值应以 binhex 格式指定。建议使用至少 256 位的数据(32 对十六进制字符或总共 64 个字符)。请注意,使用超过 512 位的密钥不会增加安全性。有关密钥指南,请参见 NIST Special Publication 800-107 Recommendation for Applications Using Approved Hash Algorithms,第 5.3.2 节 HMAC 密钥。

要生成 256 位密钥(32 对十六进制字符;总共 64 个字符):

openssl rand -hex 32

额外支持的算法

该配置还支持通过(例如)auth_jwt_algorithm RS256 进行 RSA 公钥验证。当使用 RS* 算法时,auth_jwt_key 字段必须设置为您的公钥 auth_jwt_use_keyfile 设置为 on,并且 auth_jwt_keyfile_path 应指向磁盘上的公钥。如果未提供密钥文件,NGINX 将无法启动。

使用内联密钥的 RS* 算法时,请确保将 auth_jwt_key 设置为 公钥,而不是 PEM 证书。例如:

auth_jwt_key "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0aPPpS7ufs0bGbW9+OFQ
RvJwb58fhi2BuHMd7Ys6m8D1jHW/AhDYrYVZtUnA60lxwSJ/ZKreYOQMlNyZfdqA
rhYyyUkedDn8e0WsDvH+ocY0cMcxCCN5jItCwhIbIkTO6WEGrDgWTY57UfWDqbMZ
4lMn42f77OKFoxsOA6CVvpsvrprBPIRPa25H2bJHODHEtDr/H519Y681/eCyeQE/
1ibKL2cMN49O7nRAAaUNoFcO89Uc+GKofcad1TTwtTIwmSMbCLVkzGeExBCrBTQo
wO6AxLijfWV/JnVxNMUiobiKGc/PP6T5PI70Uv67Y4FzzWTuhqmREb3/BlcbPwtM
oQIDAQAB
-----END PUBLIC KEY-----";

使用公钥文件的 RS* 算法,请按如下方式操作:

auth_jwt_use_keyfile on;
auth_jwt_keyfile_path "/path/to/pub_key.pem";

典型用例是在 http 级别指定密钥和登录 URL,然后仅对您希望保护的路径启用 JWT 身份验证(反之亦然)。未经授权的请求将导致 302 Moved Temporarily 响应,并将 Location 头设置为 auth_jwt_loginurl 指令中指定的 URL,以及一个查询字符串参数 return_url,其值为当前/尝试的 URL。

如果您希望返回 401 Unauthorized 而不是重定向,可以将 auth_jwt_redirect 关闭:

auth_jwt_redirect off;

JWT 位置

默认情况下,Authorization 头用于提供 JWT 进行验证。然而,您可以使用 auth_jwt_location 指令来指定提供 JWT 的头或 cookie 的名称:

auth_jwt_location HEADER=auth-token;  # 从 "auth-token" 头获取 JWT
auth_jwt_location COOKIE=auth-token;  # 从 "auth-token" cookie 获取 JWT

sub 验证

可选地,该模块可以验证 JWT 中是否存在 sub 声明(例如用户 ID)。您可以按如下方式启用此功能:

auth_jwt_validate_sub on;

从 JWT 中提取声明

您可以指定要从 JWT 中提取的声明,并将其放置在请求和/或响应头中。这尤其方便,因为这些声明也将作为 NGINX 变量可用。

如果您只希望将声明作为 NGINX 变量访问,您应该使用 auth_jwt_extract_var_claims,以便该声明不会作为响应头发送给客户端。然而,如果您希望该声明在响应中发送给客户端,您可以使用 auth_jwt_extract_response_claims

请注意,目前不支持 numberbooleanarrayobject 声明 -- 仅支持 string 声明。 如果您尝试提取非字符串声明,将抛出错误。

使用声明

例如,您可以配置一个 NGINX 位置,重定向到当前用户的个人资料。假设 sub=abc-123,以下配置将重定向到 /profile/abc-123

location /profile/me {
    auth_jwt_extract_var_claims sub;

    return 301 /profile/$jwt_claim_sub;
}

使用响应声明

响应声明的使用方式相同,唯一的区别是: - 变量通过 $sent_http_jwt_* 模式访问,例如 $sent_http_jwt_sub,并且 - 头部发送给客户端。

提取多个声明

您可以通过将所有声明作为单个指令的参数指定,或通过提供多个指令来提取多个声明。以下两个示例是等效的。

auth_jwt_extract_request_claims sub firstName lastName;
auth_jwt_extract_request_claims sub;
auth_jwt_extract_request_claims firstName;
auth_jwt_extract_request_claims lastName;

克隆 libjwt

  1. 按如下方式克隆此存储库(替换 <target_dir>):git clone [email protected]:benmcollins/libjwt.git <target_dir>
  2. 进入目录并切换到最新标签:git checkout $(git tag | sort -Vr | head -n 1)
  3. 更新上述 includePath 条目以匹配您选择的位置。

克隆 libjansson

  1. 按如下方式克隆此存储库(替换 <target_dir>):git clone [email protected]:akheron/jansson.git <target_dir>
  2. 进入目录并切换到最新标签:git checkout $(git tag | sort -Vr | head -n 1)
  3. 更新上述 includePath 条目以匹配您选择的位置。

验证编译

一旦您将更改保存到 .vscode/c_cpp_properties.json,您应该看到问题面板中的警告和错误消失,至少是暂时的。希望它们不会再出现,但如果出现,请确保您的包含路径设置正确。

对于使用 systemd 的 Linux 系统(可选)

export LOG_DRIVER=journald

对于其他系统或如果您更喜欢基于文件的日志(默认)

export LOG_DRIVER=json-file

重新构建测试镜像

./scripts rebuild_test

运行测试

./scripts test

检查日志 -- 根据需要调整容器名称

对于 journald(Linux 系统):

journalctl -eu docker CONTAINER_NAME=nginx-auth-jwt-test-nginx

对于 json-file 驱动程序(所有系统):

docker logs nginx-auth-jwt-test-nginx

现在您将能够看到之前测试运行的日志。最好的使用方法是打开两个终端,一个用于运行测试,另一个用于跟踪日志:

```shell
## 终端 1
./scripts test

## 终端 2 - 根据您的 LOG_DRIVER 设置选择:

## 对于 journald:
journalctl -fu docker CONTAINER_NAME=jwt-nginx-test

## 对于 json-file(默认):
docker logs -f nginx-auth-jwt-test-nginx

GitHub

您可以在 nginx-module-teslagov-jwt 的 GitHub 存储库 中找到此模块的其他配置提示和文档。