AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1121736
Accepted
Rino Bino
Rino Bino
Asked: 2023-02-02 15:24:28 +0800 CST2023-02-02 15:24:28 +0800 CST 2023-02-02 15:24:28 +0800 CST

Nginx 在 if 语句之前不处理 auth_request

  • 772

通过示例展示我遇到问题的地方可能是最简单的,所以我会直接进入......

此代码段将按原样用于启用了重写/授权模块的 Nginx。所以希望这个问题在几乎所有 Nginx 安装上都能快速轻松地重现......

server {
  listen 8081;
  add_header x-user bar;
  return 200;
}

server {
  listen 8080;

  location = /auth {
    internal;
    proxy_pass http://localhost:8081;
  }

  location / {
    auth_request /auth;
    auth_request_set $foo $upstream_http_x_user;

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }
}

上面的示例 Nginx 站点配置执行以下操作:

  1. /auth通过auth_request 呼叫发送任何请求
  2. /auth 位置将请求发送到添加标头的另一台服务器x-user bar
  3. auth_request_set$foo根据上面步骤 2 中设置的上游标头值设置一个新的 var x-user。
  4. 设置了一个新的标头,x-test该标头的值为$foo
  5. 请求继续到外部目的地。

响应正是我所期望的,并确认$foovar 设置正确:

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test'
HTTP/1.1 200 OK
x-test: bar

所以,问题来了……
我需要调整这个配置,以便在上游标头的值不正确时返回 403。

似乎是一项简单的任务。所以我添加了一个if{}条件来检查标题:

  location / {
    auth_request /auth;
    auth_request_set $foo $upstream_http_x_user;

    # this 'if' is the only part added to the original config
    if ($foo != bar) {
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }

条件if评估为真,所以我得到了 403,这不是我所期望的。所以,这不起作用:

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test'
HTTP/1.1 403 Forbidden

我意识到if 是邪恶的但是我似乎只是用它来返回应该没问题。我愿意使用任何方法来实现相同的目标——有或没有if,所以我对想法持开放态度!!

我试过做一些事情,比如将auth_request和/或if语句移动到块中server{},但似乎没有任何东西可以按照我期望的方式进行评估。


进一步的故障排除/详细信息:

我已经验证了问题是在isif之前对 is 进行了评估auth_request_set

  location / {
    auth_request /auth;
    auth_request_set $foo $upstream_http_x_user;

    if ($foo != bar) {
      # x-test never gets set because $foo is null when if evaluates
      add_header x-test $foo always;
      add_header success false always;
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }
$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test|success'
HTTP/1.1 403 Forbidden
success: false

set如果使用而不是,我已经验证这不是问题auth_request_set。这有效(但没有实现目标):

  # set works, but not auth_request_set
  location / {
    set $foo bar;

    if ($foo != bar) {
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }

这个配置有效。set之前被评估if:

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test'
HTTP/1.1 200 OK
x-test: bar

即使在上下文auth_request中,该行为仍然存在server{}:

server {
  listen 8081;
  add_header x-user bar;
  return 200;
}

server {
  listen 8080;

  auth_request /auth;
  auth_request_set $foo $upstream_http_x_user;

  location = /auth {
    internal;
    proxy_pass http://localhost:8081;
  }

  location / {

    if ($foo != bar) {
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }

}

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test|success'
HTTP/1.1 403 Forbidden
success: false

我查看了以下文档和问题:

  • 在 nginx 中返回 auth_request 后,我​​可以比较 auth_request_set 设置的变量吗?
  • https://stackoverflow.com/questions/73431103/cant-access-added-headers-using-nginx-auth-request-set
  • Nginx $upsteam_cache_status 自定义标头不会出现
  • auth_request 不阻止 return 指令,不能返回状态?
  • https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil
  • http://nginx.org/en/docs/http/ngx_http_auth_request_module.html
  • http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
  • https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
nginx
  • 2 2 个回答
  • 116 Views

2 个回答

  • Voted
  1. Best Answer
    Tero Kilkanen
    2023-02-04T12:36:06+08:002023-02-04T12:36:06+08:00

    这if是有问题的,因为它是在其他声明性配置中的命令式构造。

    因此它并不总是按预期工作。可以在IfIsEvil文章中找到更多信息。

    在这种情况下,set和auth_request_set发生在 nginx 请求处理的不同阶段,并且if处理发生在这两个阶段之间。

    不幸的是我不知道如何在 nginx 中实际做你想做的事。也许这需要在您将请求代理到的上游服务器中完成。

    • 2
  2. Rino Bino
    2023-02-07T22:32:30+08:002023-02-07T22:32:30+08:00

    这没有回答问题,请在此处查看 Tero 的回答以获取实际答案(剧透:它确实if是邪恶的,即使与 一起使用也是如此)。return

    但是,作为提供解决方法的功能性答案:这至少是一种使无效请求发送 403 的方法。proxy_pass 端点是动态的,具体取决于测试的标头。这似乎解决了用例......

    upstream barhost {
      server example.com;
    }
    
    
    map $foo $choose_upstream {
      default 127.0.0.1:8999;
    
      # cannot use hostnames here since they don't resolve. Using an upstream instead. 
      bar barhost;
    }
    
    server {
      listen 8999;
      return 403;
    }
    
    server {
      listen 8081;
      add_header x-user bar;
      return 200;
    }
    
    server {
      listen 8080;
    
      auth_request /auth;
    
      location = /auth {
        internal;
        proxy_pass http://localhost:8081;
      }
    
      location / {
        auth_request_set $foo $upstream_http_x_user;
        proxy_set_header Host example.com;
        proxy_pass http://$choose_upstream/;
      }
    }
    
    • 1

相关问题

  • Gzip 与反向代理缓存

  • nginx 作为代理的行为

  • Nginx 学习资源 [关闭]

  • 提供 70,000 个静态文件 (jpg) 的最佳方式?

  • 在 Apache、LightTPD 和 Nginx Web 服务器上提供 PHP 5.x 应用程序的现状?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve