在我的 Web 应用程序架构中,我想将 应用程序层 与 身份验证/授权层分开。
我最初的想法是这样的:
此系统的一些要求:
Nginx 提供了一些功能,但对我来说,它似乎不足以实现整个目的:
设置JWT认证,基于子请求结果进行认证 按照图像,
流程将是:
客户端访问NginxApp Server: PHP
Auth Server: any
主要由三个组件组成:
反向代理(Nginx)、网络应用程序和身份验证服务。 身份验证服务处理登录、注销和令牌刷新的路由。它负责使用
JWE和黑名单(Redis)生成访问令牌,用于即时撤销,以及使用嵌入在JWT有效负载中的声明来验证权限。此外,它还有一条关键路线,我称之为“验证”,用于“检查每个请求的令牌”和“用户权限”。
这是相关的 Nginx 配置片段:
location /secure/api {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "$http_origin";
add_header Access-Control-Allow-Credentials "true";
add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,DELETE,PUT,PATCH,HEAD";
add_header Access-Control-Allow-Headers "Accept, Authorization, Content-Type";
add_header Access-Control-Max-Age 1728000;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
auth_request /auth/verify;
auth_request_set $auth_user $upstream_http_user;
error_page 401 = @error401;
proxy_buffering off;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Keep-Alive "";
proxy_set_header Cookie "";
proxy_set_header Proxy-Connection "keep-alive";
proxy_set_header User $auth_user;
proxy_pass http://app;
}
location = /auth/verify {
internal;
proxy_method GET;
proxy_http_version 1.1;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri; //route to verify
proxy_set_header X-Original-Method $request_method; //method to verify
proxy_set_header Proxy-Connection "keep-alive";
proxy_set_header "Connection" "";
proxy_pass http://auth_server/auth/verify;
}
location @error401 {
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Origin "$http_origin" always;
return 401;
}
通过此设置,每个请求都会通过
,验证用户,并以base64形式返回
标头中的用户信息,可以由
应用程序访问。这包括登录名、用户 ID 和其他详细信息。 黑名单系统也很简单。它类似于某些 Web 系统中使用的会话登录概念。生成一个
Session-ID,允许用户使用 Redis 之类的东西访问他们在服务器端保存的信息 在黑名单系统中,我们不保存“已登录”用户的会话ID,而是保存会话已“被撤销”的用户的ID。 验证路由 检查此 Redis 存储,如果其中包含用户的 Session-ID,则
访问被拒绝,如果用户仍有权限,则必须重新登录。此时,将为他们生成一个新的 Session-ID。 需要考虑的重要一点是如何在客户端存储令牌,以避免安全漏洞并确保内部路由受到保护。