Nginx:在位置指令中匹配服务器主机名

Nginx:在位置指令中匹配服务器主机名

我有 nginx 在单个服务器指令下运行多个域,如下所示

server {
        listen       80;
        server_name  www.domain.com;
        server_name  x.domain.com;
        server_name  y.domain.com;

----
----
----
}

现在,我需要使用 location 指令来匹配子域并对其应用基本身份验证。相当于

location x.domain.com {
        auth_basic "Admin Login";
        auth_basic_user_file /etc/nginx/.htpasswd;
}

我该怎么做呢?

答案1

您可以使用正则表达式来捕获子域,然后稍后在您的位置使用它。

server {
    server_name   ~^(?<sub>\.)?(?<domain>.+)$;

    location / {
        root   /sites/$sub;
    }
}

或者,最好将所有常见配置移动到其他文件,然后为每个子域创建服务器块并包含外部文件。

server {
        server_name  www.domain.com;
        include /etc/nginx/sites-enabled/default.inc;

    location / {
        ... 
    } 
}

(对其他服务器重复此操作)

答案2

如果使用 map,则无需使用 location 指令。这是我能想到的最简单的解决方案和等效方案。您可以根据 $http_host 命名 htpasswd 文件,例如x.domain.com.htpasswd

map $http_host $auth_type {
    default "off";               #This will turn off auth-basic
    x.domain.com "Restricted";   #This or any other string will turn it back on
}

server {
    auth_basic $auth_type;
    auth_basic_user_file /etc/nginx/conf.d/$http_host.htpasswd;
}

答案3

一种选择是返回错误并将该错误发送到处理 HTTP 身份验证的位置:

if ($host = x.domain.com) {
    return 550;
}

error_page 550 = @xauth;

location @xauth {
    auth_basic "Admin Login";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

答案4

如果你有多个(子)域名,但它们的行为不正常确切地相同,则使用多个服务器块。抱歉,但这确实是最好的方法,即使您的配置较大。

您可以使用类似 if ($http_host ~ foo) 的方法进行贫民窟黑客攻击,但随后您很可能会遇到 if 的不可预测和奇怪的行为,如下所述:http://wiki.nginx.org/IfIsEvil

不要试图超越 Nginx,只需使用它提供的选项,你就会少受很多麻烦。

相关内容