在nginx中是否有一种方法可以使用多个auth_request指令?

17

我想使用多个auth_request指令来尝试在多个服务器上进行身份验证 - 即如果第一个身份验证服务器返回403,则尝试第二个身份验证服务器。 我尝试了一种简单的方法,像这样:

location /api {
    satisfy any;
    auth_request    /auth-1/;
    auth_request    /auth-2/;
    proxy_pass http://api_impl;
}

location /auth-1/ {
    internal;
    proxy_pass              http://auth_server_1;
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
    proxy_set_header        X-Original-URI $request_uri;
}

location /auth-2/ {
    internal;
    proxy_pass              http://auth_server_2;
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
    proxy_set_header        X-Original-URI $request_uri;
}

但是nginx无法解析配置文件。我收到了以下响应

nginx: [emerg] "auth_request" directive is duplicate

有没有一种方法可以在nginx中实现这样的功能?

2个回答

4

在谷歌上搜索后,我找到了这个问题并提出了我的解决方案:

  • 设置一个上游服务器,传递给环回Nginx服务器
  • 使那些上游服务器做你的 /auth-1 和 /auth-2 端点所做的事情,除了在认证错误时返回503(除了最后一个在链中仍然返回401以向Nginx发信号,表示没有更多可尝试的服务器)
  • 告诉Nginx在 /auth 上只使用这个上游服务器,因此它将按顺序尝试所有身份验证“服务器”(由于 503 返回代码),直到其中一个成功或最后一个返回401。
upstream auth {
    server 127.0.2.1:8000 max_fails=0;
    server 127.0.2.1:8001 max_fails=0;
    server 127.0.2.1:8002 max_fails=0;
}

# Method 1
server {
    listen 127.0.2.1:8000;

    location / {
        proxy_pass              http://auth_server_1; # Returns **503** on failure
        proxy_pass_request_body off;
        proxy_set_header        Content-Length "";
        proxy_set_header        X-Original-URI $request_uri;
    }
}

# Method 2
server {
    listen 127.0.2.1:8001;

    location / {
        proxy_pass              http://auth_server_2; # Returns **503** on failure
        proxy_pass_request_body off;
        proxy_set_header        Content-Length "";
        proxy_set_header        X-Original-URI $request_uri;
    }
}

# Method 3
server {
    listen 127.0.2.1:8002;

    location / {
        proxy_pass              http://auth_server_3; # Returns **401** on failure
        proxy_pass_request_body off;
        proxy_set_header        Content-Length "";
        proxy_set_header        X-Original-URI $request_uri;
    }
}

server {
    # ...
    location /api {
        auth_request    /auth;
        proxy_pass http://api_impl;
    }

    location /auth {
        proxy_pass http://auth/;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URL $request_uri;
        proxy_next_upstream error timeout http_503;
    }
    # ...
}

1

我曾经遇到过类似的问题,但是找到了一种不同的解决方案,在某些情况下可能是可接受的。它本质上创建了一个双代理层,这会带来显著的性能损失。第一层代理用于“身份验证”,第二层代理用于“授权”。

以下配置未经测试,仅用于传达概念而非工作示例。

### What I wanted

location /protected_path {
    auth_request /authenticate; # Login to IDP
    auth_request /authorize;    # Apply Role/Group based authorization
    # Final routing logic
}

### My solution

server {
    listen 443;
    location /protected_path {
        auth_request /authenticate;
        auth_request_set $idp-data $arbitrary_data_from_idp_server;
        proxy_pass http://localhost:8000;
        proxy_set_header Arbitrary-Header $idp-data;
    }
}

server {
    listen 127.0.0.1:8000;
    location /protected_path {
        auth_request /authorize;
        # Final routing logic
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接