【NGINX--5】身份验证

1、HTTP 基本身份验证

需要通过 HTTP 基本身份验证保护应用或内容。

生成以下格式的文件,其中的密码使用某个受支持的格式进行了加密或哈希处理:

bash 复制代码
# comment 
name1:password1 
name2:password2:comment 
name3:password3

第一个字段是用户名,第二个字段是密码,冒号是分隔符。第三个字段为可选项,您可以使用该字段对每个用户进行评论。NGINX 能理解几种不同的密码格式,其中一个是使用 C 函数 crypt() 加密的密码。该函数通过 openssl passwd 命令暴露在命令行中。安装 openssl 后,您可以使用以下命令创建加密的密码字符串:

bash 复制代码
$ openssl passwd MyPassword1234

输出结果将是一个字符串,可供 NGINX 在密码文件中使用。

在 NGINX 配置中使用 auth_basic 和 auth_basic_user_file 指令,实现基本身份验证:

bash 复制代码
location / {
    auth_basic "Private site"; 
    auth_basic_user_file conf.d/passwd;
}

您可以在 http、server 或 location 上下文中使用 auth_basic 指令。auth_basic 指令带一个字符串参数,如有未经授权的用户访问,该参数将显示在基本身份验证弹窗中。auth_basic_user_file 指定了用户文件的路径。

如要测试配置,您可以使用带 -u 或 --user 标志的 curl 来构建请求的 Authorization 请

求头:

bash 复制代码
$ curl --user myuser:MyPassword1234 https://localhost

详解

您可以通过几种方式生成具有不同格式和安全等级的基本身份验证密码。Apache 的htpasswd 命令也可以生成密码。openssl 和 htpasswd 都可以使用 apr1 算法生成密码,并且 NGINX 也能理解这种格式的密码。该密码也可以是轻型目录访问协议(LDAP)和 Dovecot 使用的 Salted SHA-1 格式。NGINX 支持其他更多格式和哈希算法;然而,许多算法容易遭到暴力破解攻击,因此人们认为这些算法不安全。

您可以使用基本身份验证来保护整个 NGINX 主机的上下文、特定的虚拟服务器甚至只是特定的 location 代码块。基本身份验证不会取代 Web 应用的用户身份验证,但可以保护私人信息的安全。实际上,基本身份验证是由服务器返回 401 Unauthorized HTTP 代码和响应头 WWW-Authenticate 完成的。该响应头的值为Basic realm="your string"。收到此响应后,浏览器将提示输入用户名和密码。用户名和密码用冒号连接和分隔,然后用 base64 编码,最后在名为 Authorization 的请求头中发送。Authorization 请求头将指定一个 Basic 和 user:password 编码字符串。服务器对请求头进行解码,并根据提供的 auth_basic_user_file 进行验证。由于用户名和密码字符串仅通过 base64 编码,我们建议在基本身份验证中使用 HTTPS。

2、身份验证子请求

希望通过第三方身份验证系对请求进行身份验证。

使用 http_auth_request_module 请求访问身份验证服务,在响应请求之前验证身份:

bash 复制代码
location /private/ { 
    auth_request /auth;
    auth_request_set $auth_status $upstream_status;
}
location = /auth { 
    internal;
    proxy_pass http://auth-server; 
    proxy_pass_request_body off; 
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
}

auth_request 指令带一个 URI 参数,该参数必须是本地内部位置。auth_request_set 指令允许您设置身份验证子请求的变量。
详解

http_auth_request_module 可验证 NGINX 服务器处理的每个请求的身份。该模块将使用子请求来确定是否授予请求访问权。子请求是指 NGINX 将请求传递给内部替代位置,并在将请求路由到目的地之前观察它的响应。auth 位置将原始请求(包括正文和请求头)传递到身份验证服务器。子请求的 HTTP 状态码决定是否授予请求访问权。如果子请求返回 HTTP 200 状态码,则表示身份验证成功,请求已完成。如果子请求返回HTTP 401 或 403,则原始请求也将返回 HTTP 401 或 403。

如果您的身份验证服务未请求请求正文,则可以使用 proxy_pass_request_body 指令删除请求正文,如上所示。这种做法可减少请求的大小和时间。由于响应正文被丢弃,Content-Length 请求头必须设置为空字符串。如果身份验证服务需要知道请求访问的URI,则需要将该值放入身份验证服务检查和验证的自定义请求头中。如果您确实希望将子请求中的某些内容保留给身份验证服务(例如响应头或其他信息),您可以使用auth_request_set 指令从响应数据中创建新的变量。

3、使用 NGINX Plus 验证 JWT

需要在使用 NGINX Plus 处理请求之前验证 JWT。

使用 NGINX Plus 的 HTTP JWT 身份验证模块来验证令牌签名,并将 JWT 声明和请求头作为 NGINX 变量嵌入:

bash 复制代码
location /api/ {
    auth_jwt "api"; 
    auth_jwt_key_file conf/keys.json;
}

此配置可以验证该位置的 JWT。auth_jwt 指令传递一个字符串,该字符串被用作身份验证领域。auth_jwt 配置带一个保存 JWT 的变量的可选令牌参数。默认情况下,根据JWT 标准使用 Authentication 请求头。auth_jwt 指令还可用于从继承的配置中消除所需的 JWT 身份验证的影响。要关闭(off)身份验证,只需将关键字传递给 auth_jwt 指令。要取消继承的身份验证要求,只需将 off 关键字传递到 auth_jwt 指令。auth_jwt_key_file 带一个参数。该参数是采用标准 JSON Web Key(JWK)格式的密钥文件的路径。
详解

NGINX Plus 支持验证 JSON Web 签名类型的令牌,而不是将整个令牌进行加密的JSON Web 加密类型。NGINX Plus 支持验证使用 HS256、RS256 和 ES256 算法签名的签名。使用 NGINX Plus 验证令牌可以节省向身份验证服务发出子请求所需的时间和资源。NGINX Plus 可破解 JWT 请求头和有效载荷,并将标准请求头和声明捕获到嵌入式变量中,供您使用。auth_jwt 指令可在 http、server、location 及 limit_except 上下文中使用。

参考资料
RFC JSON Web Signature 标准文档
RFC JSON Web 算法标准文档
RFC JSON Web Token 标准文档
NGINX Plus JWT 身份验证
"借助 JWT 和 NGINX Plus 验证 API 客户端身份"

4、创建 JSON Web Key

需要使用 JSON Web Key(JWK)才能使用 NGINX Plus。

NGINX Plus 使用 RFC 标准中指定的 JWK 格式。该标准允许在 JWK 文件中包含一个关键对象数组。

以下是该密钥文件的示例:

bash 复制代码
{"keys":
    [
       {
           "kty":"oct",
           "kid":"0001",
           "k":"OctetSequenceKeyValue"
       },
       {
           "kty":"EC",
           "kid":"0002"
           "crv":"P-256",
           "x": "XCoordinateValue",
           "y": "YCoordinateValue",
           "d": "PrivateExponent",
           "use": "sig"
       },
       {
           "kty":"RSA",
           "kid":"0003"
           "n": "Modulus",
           "e": "Exponent",
           "d": "PrivateExponent"
       }
   ]
}

所示的 JWK 文件演示了 RFC 标准中指出的三类初始密钥。这些密钥的格式也是 RFC 标准的一部分。kty 属性是密钥类型。该文件显示了三种密钥类型:Octet Sequence(oct)、EllipticCurve(EC)和 RSA 类型。kid 属性是密钥 ID。这些密钥的标准中指定了其他属性。更多信息请查看这些标准的 RFC 文档。
详解

有许多提供不同语言的库可以生成 JWK。建议创建一个密钥服务,作为 JWK 的中央权限,以定期创建和轮换您的 JWK。为了增强安全性,建议让 JWK 与 SSL/TLS 证书一样安全。使用适当的用户和组权限保护密钥文件。最好将它们保存在主机的内存中。您可以通过创建类似 ramfs 的内存文件系统来实现。定期轮换密钥也很重要;您可以选择创建一个密钥服务来创建公钥和私钥,并通过 API 将它们提供给应用和 NGINX。

参考资料
RFC JSON Web Key 标准文档

5、使用 NGINX Plus 验证 JSON Web Token

使用 NGINX Plus 验证 JSON Web Token。

使用 NGINX Plus 自带的 JWT 模块保护位置或服务器,并指示 airt_jwt 指令使用$cookie_auth_token 作为要验证的令牌:

bash 复制代码
location /private/ {
    auth_jwt "Google Oauth" token=$cookie_auth_token; 
    auth_jwt_key_file /etc/nginx/google_certs.jwk;
}

此配置指示 NGINX Plus 通过 JWT 验证保护 /private/ URI 路径。Google OAuth 2.0 OpenID Connect 使用 cookie auth_token 而不是默认的 bearer 令牌。因此,您必须指示 NGINX 在此 cookie 中查找令牌,而不是在 NGINX Plus 的默认位置中查找。我们将在实操指南 6.6 中介绍如何将 auth_jwt_key_file 位置设置为任意路径。
详解

此配置说明了如何使用 NGINX Plus 验证 Google OAuth 2.0 OpenID Connect JWT。NGINX Plus 的 HTTP JWT 身份验证模块支持验证符合 RFC JSON Web Signature 规范的 JWT,允许任何使用 JWT 的 SSO 授权立即在 NGINX Plus 层中进行验证。OpenID 1.0 协议层位于 OAuth 的上面。OpenID 2.0 身份验证协议添加了身份,支持使用 JWT 来证明发送请求的用户的身份。NGINX Plus 可通过令牌的签名验证令牌自签名以来是否经过修改。这允许 Google 使用一种异步签名方法,可在保护其私人JWK 的同时分发公共 JWK。
参考资料
"借助 JWT 和 NGINX Plus 验证 API 客户端身份"

6、使用 NGINX Plus 自动获取和缓存 JSON Web Key Set

希望 NGINX Plus 自动请求提供商的 JSON Web Key Set(JWKS)并进行缓存。

利用缓存区和 auth_jwt_key_request 指令自动更新密钥:

bash 复制代码
proxy_cache_path /data/nginx/cache levels=1 keys_zone=foo:10m;
server {
     # ...
     location / {
         auth_jwt "closed site";
         auth_jwt_key_request /jwks_uri;
     }
     location = /jwks_uri {
         internal;
         proxy_cache foo;
         proxy_pass https://idp.example.com/keys;
     }
}

在此示例中,auth_jwt_key_request 指令指示 NGINX Plus 从内部子请求中检索 JWK。该子请求被定向到 /jwks_uri,后者将请求代理给身份提供商。默认请求缓存时间为 10 分钟,以限制开销。
详解

NGINX Plus R17 中引入了 auth_jwt_key_request 指令。此功能支持 NGINX Plus 服务器在发出请求时动态更新其 JWK。使用子请求方法来获取 JWK,这意味着指令指向的位置必须是 NGINX Plus 服务器本地的位置。在上面的示例中,子请求的位置被锁定,以确保仅响应内部的 NGINX Plus 请求。还可使用缓存来确保仅在必要时发出 JWK 检索请求,并且不会导致身份提供商过载。auth_jwt_key_request 指令在 http、server、location 和 limit_except 上下文中有效。
参考资料
"借助 JWT 和 NGINX Plus 验证 API 客户端身份"
NGINX Plus"借助 JSON Web Key Set 缓存加快 JWT 验证"

7、使用 NGINX Plus 通过现有的 OpenID Connect SSO 验证用户身份

希望将 NGINX Plus 与 OpenID Connect(OIDC)身份提供商集成在一起。

该解决方案由许多配置要素和一些 NGINX JavaScript 代码组成。身份提供商(IdP)必须支持 OpenID Connect 1.0。NGINX Plus 将在授权代码流中充当 OIDC 的中继方。NGINX Inc. 维护了一个 GitHub 公共仓库,该仓库包含作为 OIDC 与 NGINX Plus 集成参考实现的配置和代码。"其他参考资料"部分中的仓库链接提供了关于如何使用自己的 IdP 设置参考实现的最新说明。

详解

该解决方案只与参考实现有关,可确保各位读者拥有最新的解决方案。提供的参考将NGINX Plus 配置为 OpenID Connect 1.0 授权代码流的中继方。在此配置中,如果将对受保护资源未经授权的请求发送到 NGINX Plus,NGINX Plus 首先会将该请求重定向到 IdP。IdP 会让客户端完成自己的登录流程,然后向 NGINX Plus 返回一个身份验证代码。然后,NGINX Plus 直接与 IdP 通信,用身份验证代码交换一组 ID 令牌。这些令牌使用 JWT 进行验证,并存储在 NGINX Plus 的键值(key-value)存储中。通过使用键值存储,采用高可用性(HA)配置的所有 NGINX Plus 节点都能获得这组令牌。在这个过程中,NGINX Plus 为客户端生成了一个会话 cookie,该 cookie 被用于在键值存储中查找令牌的密钥。然后,客户端的 cookie 被重定向到初始请求的资源。随后的请求将通过使用 cookie 查找 NGINX Plus 键值存储中的 ID 令牌来进行验证。

该功能支持与大多数主要身份提供商进行集成,包括 CA 单点登录(以前称为SiteMinder)、ForgeRock OpenAM、Keycloak、Okta、OneLogin 和 Ping Identity。作为一项标准,OIDC 与身份验证密切相关 ------ 前面提到的身份提供商只是可能集成的一个子集。
参考资料
"借助 OpenID Connect 和 NGINX Plus 对访问当前应用的用户进行身份验证"
OpenID Connect
NGINX OpenID Connect GitHub

相关推荐
青木沐1 小时前
Jenkins介绍
运维·jenkins
WTT00111 小时前
2024楚慧杯WP
大数据·运维·网络·安全·web安全·ctf
苹果醋32 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
日记跟新中2 小时前
Ubuntu20.04 修改root密码
linux·运维·服务器
唐小旭2 小时前
服务器建立-错误:pyenv环境建立后python版本不对
运维·服务器·python
BUG 4042 小时前
Linux——Shell
linux·运维·服务器
大霞上仙3 小时前
Linux 多命令执行
linux·运维·服务器
冷心笑看丽美人3 小时前
探索 Samba 服务器:搭建跨平台文件共享的桥梁
运维·服务器
晨欣3 小时前
Kibana:LINUX_X86_64 和 DEB_X86_64两种可选下载方式的区别
linux·运维·服务器