浅析nginx配置server_name为多个时的坑

一、问题背景

  我们一个服务器设置了2个域名,分别对应2个项目。监听 80  端口写了2个 server_name。比如这样server_name配置改为:

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

  见这篇文章有类似问题:https://blog.csdn.net/u011296355/article/details/106740860

二、问题定位

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

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_name 始终是 www.abc.com 的原因了。

四、解决方式

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

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

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

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

fastcgi_param SERVER_NAME $server_name;
// 修改为:
fastcgi_param SERVER_NAME $host;

3、$host 变量的解析都是当前请求的host,不会受 server_name 是否配置多个域名的影响。

posted @ 2017-06-12 23:04  古兰精  阅读(1609)  评论(0编辑  收藏  举报