nginx server_name配置多个域名时的坑

 更新时间:2025年05月28日 09:20:12   作者:zzhongcy  
Nginx配置多个server_name时,$server_name默认取第一个值,导致PHP获取错误,下面就来介绍一下该问题的解决,感兴趣的可以了解一下

server_name 指令详解

server_name 指令设置基于域名的虚拟主机,⼀个ip的服务器可以配置多个域名。下⾯这些server_name是有效的:

  • server_name domain.com;
  • server_name domain.com www.domain.com;
  • server_name *.domain.com;
  • server_name .domain.com;
  • server_name domain.*;
  • server_name "";

多个域名之间以空格分隔。nginx允许⼀个虚拟主机有⼀个或多个名字,也可以使⽤通配符"*"来设置虚拟主机的名字。

server_name指令在接到请求后的匹配顺序分别为:

  • 1、准确的server_name匹配,例如:domain.com www.domain.com
  • 2、以通配符开始的字符串: .domain.com  .domain.com
  • 3、以通配符结束的字符串:www.
  • 4、匹配正则表达式:~^(?.+).domain.com$

nginx将按照1,2,3,4的顺序对server name进⾏匹配,有⼀项匹配以后就会停⽌搜索,类似于location指令。

背景

为了区分线上环境和测试环境,我弄了个自己测试专用的域名test.daemoncoder.com,线上环境的正式域名是www.daemoncoder.com。nginx里的server_name配置改为:

# 只列出了我们关心的配置,省略了其他无关部分
server {
    server_name www.daemoncoder.com test.daemoncoder.com;
    ...
}

但是使用时发现请求一直报错,重定向到错误页面,于是开始了问题的定位。

问题的定位

根据业务上报错时打的日志,定位到请求公共处理的部分里有这么一个判断:

if ($_SERVER['SERVER_NAME'] != parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) {
    $this->redirectError();
}

判断请求referer里解析出的域名如果和nginx里的$server_name变量里的域名如果不一样,就跳到错误页面,也是前面说的问题。

那么问题来了,看referer中的域名为什么和 $_SERVER['SERVER_NAME'] 不一致呢?我请求用的链接形式如 http://test.daemoncoder.com/xxx 这种形式,但是最终在PHP这一层取到 $_SERVER['SERVER_NAME'] 的值为 www.daemoncoder.com,而 HTTP_REFERER 里的域名为:test.daemoncoder.com。

可以看到 SERVER_NAME 的取值和我们的预期不一致,nginx是怎么把这个变量传过来的,需要从 nginx 的 fastcgi_params 配置文件中找一下 SERVER_NAME 的定义:

fastcgi_param SERVER_NAME $server_name;

可以看到 nginx 里的 $server_name 变量就是我们PHP里取的$_SERVER['SERVER_NAME'] 的来源。

问题的原因

通过上面的定位,我们基本可以看到问题的根本原因了(敲黑板,划重点):

当nginx配置里一个server节点下,server_name配置多个域名时,$server_name变量的值都是配置的第一个。

再回顾下我的 nginx 配置:

# 只列出了我们关心的配置,省略了其他无关部分
server {
    server_name www.daemoncoder.com test.daemoncoder.com;
    ...
}

server_name 结点有两个:www.daemoncoder.com 和 test.daemoncoder.com,当我用测试域名去访问页面的时候,可以匹配到 test.daemoncoder.com 这个域名,所以会根据当前这个server节点的配置来处理这个请求,但是 nginx 会把 $server_name 的值设置为当前 server 节点的配置的第一个 server_name,也就是 www.daemoncoder.com。如果配置改为:

server_name test.daemoncoder.com www.daemoncoder.com;

那么用测试域名请求就可以得到期望的值了(但是正式域名就出问题了)。

解决方式

第一种方式就是把配置文件按域名拆分到各自单独的server节点下,也就是:

# 省略其他无关部分
server {
    server_name www.daemoncoder.com;
    ...
}
server {
    server_name test.daemoncoder.com;
    ...
}

这样用不同的域名访问会落到各自对应的配置中,解析到的 $server_name 也都是各自的值。

第二种方式是修改 nginx SERVER_NAME 使用 $host 变量, 也就是把 

fastcgi_param SERVER_NAME $server_name;

修改为:

fastcgi_param SERVER_NAME $host;

$host变量的解析都是当前请求的host,不会受 server_name 是否配置多个域名的影响,这样我们在PHP里取 $_SERVER['SERVER_NAME'] 取出的值就是实际请求的域名,也可以解决问题(但是代码里的这个判断逻辑在测试环境似乎就没有意义了,问题不大)。

其他

有多个域名时(server_name other.domain.com www. domain.com;):fastcgi_param SERVER_NAME $server_name ,$server_name 会取值第一个域名(other.domain.com)。

$host 有可能等于 $server_name ,也可能是IP地址(直接通过访问此优先顺序取值:请求行中的主机名,或“主机”请求标头字段中的主机名,或与请求匹配的服务器名。

$1|$2|$3 ...是nginx在匹配正则时生成的变量,用于捕获一个正则表达式括号中匹配的字符串(从左到右依次存储在$1|$2|$3 ...中),新值覆盖旧值,可以使用变量保存需要用到的值set $pre $1

到此这篇关于nginx server_name配置多个域名时的坑的文章就介绍到这了,更多相关nginx server_name配置多个域名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • LNMP 解决Access Denied错误详细介绍

    LNMP 解决Access Denied错误详细介绍

    这篇文章主要介绍了LNMP 解决Access Denied错误详细介绍的相关资料,需要的朋友可以参考下
    2016-10-10
  • Nginx HttpHeader增加几个关键的安全选项问题小结

    Nginx HttpHeader增加几个关键的安全选项问题小结

    本文给大家介绍Nginx HttpHeader增加几个关键的安全选项问题小结,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2024-12-12
  • nginx 防盗链防爬虫配置详解

    nginx 防盗链防爬虫配置详解

    这篇文章主要介绍了nginx 防盗链防爬虫配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Nginx搭配cpolar实现远程开发无缝协作全过程

    Nginx搭配cpolar实现远程开发无缝协作全过程

    Nginx是一款高性能的本地Web服务器,以其卓越的稳定性和灵活的配置能力,成为开发者搭建本地服务的首选工具,本文将介绍如何利用 Ubuntu操作系统、Docker容器技术以及cpolar内网穿透工具来实现公网远程访问本地Nginx服务器的具体操作流程,需要的朋友可以参考下
    2026-01-01
  • Nginx配置及热升级的详细介绍

    Nginx配置及热升级的详细介绍

    Nginx与Apache一样,都是web服务器,但是Nginx比Apache多一些功能,比如Nginx可以做代理,可以做负载均衡,这篇文章主要介绍了Nginx配置以及热升级,需要的朋友可以参考下
    2024-07-07
  • Centos离线安装Nginx全过程

    Centos离线安装Nginx全过程

    文章讲述了如何在CentOS系统上离线安装Nginx环境,包括准备必要的依赖库(如C++环境、openssl、pcre、zlib),编译Nginx源码,以及启动Nginx并验证安装是否成功
    2025-11-11
  • nginx搭建图片服务器的过程详解(root和alias的区别)

    nginx搭建图片服务器的过程详解(root和alias的区别)

    这篇文章主要介绍了nginx搭建图片服务器(root和alias的区别)的过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Nginx中location实现多条件匹配的方法详解

    Nginx中location实现多条件匹配的方法详解

    在 Nginx 中,location 指令用于匹配请求的 URI,虽然 location 本身是基于单一匹配规则的,但可以通过多种方式实现多个条件的匹配逻辑,下面小编就来为大家介绍一下具体实现方法吧
    2025-03-03
  • 国内一些常用PHP的CMS的Nginx服务器的伪静态规则整理

    国内一些常用PHP的CMS的Nginx服务器的伪静态规则整理

    当我们从apache服务器转向Nginx服务器的时候,它们的伪静态规则就不一样了,所以你熟悉Nginx服务器的伪静态规则,自己写当然也好
    2011-03-03
  • nginx后端节点的健康检查和nginx平滑升级方式

    nginx后端节点的健康检查和nginx平滑升级方式

    本文介绍了Nginx反向代理的ngx_http_proxy_module和ngx_http_upstream_module模块,以及淘宝开发的nginx_upstream_check_module模块,并介绍了Nginx平滑升级原理及实战操作,最后总结了Nginx版本升级的方法
    2026-04-04

最新评论