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 指令,可以在 http、server 或 location 级别指定。有关更多信息,请参见 示例 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。
请注意,目前不支持 number、boolean、array 和 object 声明 -- 仅支持 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
- 按如下方式克隆此存储库(替换
<target_dir>):git clone [email protected]:benmcollins/libjwt.git <target_dir> - 进入目录并切换到最新标签:
git checkout $(git tag | sort -Vr | head -n 1) - 更新上述
includePath条目以匹配您选择的位置。
克隆 libjansson
- 按如下方式克隆此存储库(替换
<target_dir>):git clone [email protected]:akheron/jansson.git <target_dir> - 进入目录并切换到最新标签:
git checkout $(git tag | sort -Vr | head -n 1) - 更新上述
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 存储库 中找到此模块的其他配置提示和文档。