欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

如何用Nginx搭建统一网关身份验证解决方案

最编程 2024-07-27 16:10:22
...

简介

当我们有多个服务需要共用一个鉴权接口时,使用Nginx也可以简单实现统一鉴权。

我们需要用到ngx_http_auth_request_module 模块,它可以基于子请求的结果实现客户端授权。

高版本(1.12+)已经默认安装该模块,或者使用--with-http_auth_request_module开启此模块。

官方示例:

location /private/ {
    auth_request /auth;
    ...
}

location = /auth {
    proxy_pass ...
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
}

如果子请求返回 2xx 响应代码,则允许访问。如果返回 401 或 403,则使用相应的错误代码拒绝访问。子请求返回的任何其他响应代码都被视为错误。

对于 401 错误,客户端还从子请求响应中接收到WWW-Authenticate请求头。

示例

我们来实现一个简单示例看他是如何工作的。

location /auth {
    internal; # 只允许内部调用,外部调用报404
    proxy_pass http://localhost:8081;
    proxy_pass_request_body off; # 不向上游发送包体
    proxy_set_header Content-Length ""; # 同上,看情况加或不加
    proxy_set_header X-Original-URI $request_uri; # 传递真实请求路径
    proxy_set_header X-Original-Remote-Addr $remote_addr; # 传递真实访问者地址
    proxy_set_header X-Original-Host $host; # 传递真实请求地址
}

location /secret {
    auth_request /auth;
    auth_request_set $user $upstream_http_x_forwarded_user;
    proxy_set_header X-User $user; # 可以传递Header
    add_header Set-Cookie $user; # 可以传递Cookie
    proxy_pass http://localhost:8080;
}

我这里开了两个服务,一个是localhost:8081/auth提供鉴权服务,而访问localhost:8080/secret服务时需要先鉴权。

@Slf4j
@RestController
public class DemoController {

    @GetMapping("/auth")
    public ResponseEntity auth(HttpServletResponse response) {
        log.info("authing user");
        response.addHeader("X-Forwarded-User", "username=root");
        return ResponseEntity.ok("auth passed");
    }

    @GetMapping("/secret")
    public ResponseEntity secret(HttpServletRequest request) {
        String xUser = request.getHeader("X-User");
        log.info("current user is {}", xUser);
        return ResponseEntity.ok("see secret");
    }
}

流程:

  1. 客户端请求/secret时,Nginx会将请求转发到/auth
  2. 我们在/auth接口中自定义鉴权流程,然后将结果写入响应体的X-Forwarded-User头中
  3. 如果鉴权失败,Nginx会根据设置的状态码进行处理
  4. 如果鉴权成功,Nginx会将X-Forwarded-User赋值给$user,再将$user赋值给X-User和Cookie
  5. Nginx会携带X-User请求头和Cookie访问/secret,我们在/secret接口中可以拿到X-User请求头和Cookie,可以用来做权限过滤
  6. 客户端收到/secret的响应时,也会带上Cookie

参考
Validating OAuth 2.0 Access Tokens with NGINX and NGINX Plus