Maison php教程 php手册 如何正确配置Nginx+PHP及正确的nginx URL重写

如何正确配置Nginx+PHP及正确的nginx URL重写

Jun 06, 2016 pm 07:53 PM
nginx url 如何 correct 配置

对很多人而言,配置NginxPHP无外乎就是搜索一篇教程,然后拷贝粘贴。听上去乎也没什么问题,可惜实际上网络上很多资料本身年久失修,漏洞百出,如果大家不求甚解,一味的拷贝粘贴,早晚有一天会为此付出代价。 假设我们用PHP实现了一个前端控制器,或者直白

对很多人而言,配置Nginx+PHP无外乎就是搜索一篇教程,然后拷贝粘贴。听上去似乎也没什么问题,可惜实际上网络上很多资料本身年久失修,漏洞百出,如果大家不求甚解,一味的拷贝粘贴,早晚有一天会为此付出代价。

假设我们用PHP实现了一个前端控制器,或者直白点说就是统一入口:把PHP请求都发送到同一个文件上,然后在此文件里通过解析「REQUEST_URI」实现路由。

此时很多教程会教大家这样配置Nginx+PHP:

server {
    listen 80;
    server_name foo.com;

    root /path;

    location / {
        index index.html index.htm index.php;

        if (!-e $request_filename) {
            rewrite . /index.php last;
        }
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /path$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
    }
}
Copier après la connexion

这里面有很多错误,或者说至少是坏味道的地方,大家看看能发现几个。

我们有必要先了解一下Nginx配置文件里指令的继承关系:Nginx配置文件分为好多块,常见的从外到内依次是「http」、「server」、「location」等等,缺省的继承关系是从外到内,也就是说内层块会自动获取外层块的值作为缺省值(有例外,详见参考)。

参考:UNDERSTANDING THE NGINX CONFIGURATION INHERITANCE MODEL

让我们先从「index」指令入手吧,在问题配置中它是在「location」中定义的:

location / {
    index index.html index.htm index.php;
}
Copier après la connexion

一旦未来需要加入新的「location」,必然会出现重复定义的「index」指令,这是因为多个「location」是平级的关系,不存在继承,此时应该在「server」里定义「index」,借助继承关系,「index」指令在所有的「location」中都能生效。

参考:Nginx Pitfalls

接下来看看「if」指令,说它是大家误解最深的Nginx指令毫不为过:

if (!-e $request_filename) {
    rewrite . /index.php last;
}
Copier après la connexion

很多人喜欢用「if」指令做一系列的检查,不过这实际上是「try_files」指令的职责:

try_files $uri $uri/ /index.php;
Copier après la connexion

除此以外,初学者往往会认为「if」指令是内核级的指令,但是实际上它是rewrite模块的一部分,加上Nginx配置实际上是声明式的,而非过程式的,所以当其和非rewrite模块的指令混用时,结果可能会非你所愿。

参考:IfIsEvil and How nginx “location if” works

下面看看「fastcgi_params」配置文件:

include fastcgi_params;
Copier après la connexion

Nginx有两份fastcgi配置文件,分别是「fastcgi_params」和「fastcgi.conf」,它们没有太大的差异,唯一的区别是后者比前者多了一行「SCRIPT_FILENAME」的定义:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
Copier après la connexion

注意:$document_root 和 $fastcgi_script_name 之间没有 /。

原本Nginx只有「fastcgi_params」,后来发现很多人在定义「SCRIPT_FILENAME」时使用了硬编码的方式,于是为了规范用法便引入了「fastcgi.conf」。

不过这样的话就产生一个疑问:为什么一定要引入一个新的配置文件,而不是修改旧的配置文件?这是因为「fastcgi_param」指令是数组型的,和普通指令相同的是:内层替换外层;和普通指令不同的是:当在同级多次使用的时候,是新增而不是替换。换句话说,如果在同级定义两次「SCRIPT_FILENAME」,那么它们都会被发送到后端,这可能会导致一些潜在的问题,为了避免此类情况,便引入了一个新的配置文件。

参考:FASTCGI_PARAMS VERSUS FASTCGI.CONF – NGINX CONFIG HISTORY

此外,我们还需要考虑一个安全问题:在PHP开启「cgi.fix_pathinfo」的情况下,PHP可能会把错误的文件类型当作PHP文件来解析。如果Nginx和PHP安装在同一台服务器上的话,那么最简单的解决方法是用「try_files」指令做一次过滤:

try_files $uri =404;
Copier après la connexion

参考:Nginx文件类型错误解析漏洞

依照前面的分析,给出一份改良后的版本,是不是比开始的版本清爽了很多:

server {
    listen 80;
    server_name foo.com;

    root /path;
    index index.html index.htm index.php;

    location / {
<pre class="brush:php;toolbar:false"><pre class="brush:php;toolbar:false">#  此处注释部分URL重写的正确写法 修改为下面 那一行替代
#  if (!-e $request_filename) {
#      rewrite . /index.php last;
#  }
<span>try_files $uri $uri/ /index.php$is_args$args;#这里后面的 $is_args$args是为了获取URL参数的,不获取可省略</span>
Copier après la connexion
}
 location ~ \.php$ {                       
           try_files $uri =404;#这里加入这一行,防止出错的 页面被PHP解析                       
           include fastcgi.conf;                       
           fastcgi_pass 127.0.0.1:9000;        <span>    
 }
</span><span>}</span>
Copier après la connexion

实际上还有一些瑕疵,主要是「try_files」和「fastcgi_split_path_info」不够兼容,虽然能够解决,但方案比较丑陋,具体就不多说了,有兴趣的可以参考问题描述。

补充:因为「location」已经做了限定,所以「fastcgi_index」其实也没有必要。

希望大家以后不要再拷贝粘贴了,如果实在改不了,那么就请拷贝粘贴本文。

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment configurer le nom de domaine du serveur cloud dans nginx Comment configurer le nom de domaine du serveur cloud dans nginx Apr 14, 2025 pm 12:18 PM

Comment configurer un nom de domaine NGINX sur un serveur cloud: Créez un enregistrement A pointant vers l'adresse IP publique du serveur cloud. Ajoutez des blocs d'hôtes virtuels dans le fichier de configuration Nginx, en spécifiant le port d'écoute, le nom de domaine et le répertoire racine du site Web. Redémarrez Nginx pour appliquer les modifications. Accéder à la configuration du test de nom de domaine. Autres notes: Installez le certificat SSL pour activer HTTPS, assurez-vous que le pare-feu autorise le trafic Port 80 et attendez que la résolution DNS prenne effet.

Comment démarrer le serveur Nginx Comment démarrer le serveur Nginx Apr 14, 2025 pm 12:27 PM

Le démarrage d'un serveur Nginx nécessite différentes étapes en fonction des différents systèmes d'exploitation: Système Linux / Unix: Installez le package NGINX (par exemple, en utilisant Apt-Get ou Yum). Utilisez SystemCTL pour démarrer un service NGINX (par exemple, sudo systemctl start nginx). Système Windows: téléchargez et installez les fichiers binaires Windows. Démarrer Nginx à l'aide de l'exécutable Nginx.exe (par exemple, nginx.exe -c conf \ nginx.conf). Peu importe le système d'exploitation que vous utilisez, vous pouvez accéder au serveur IP

Comment vérifier la version nginx Comment vérifier la version nginx Apr 14, 2025 am 11:57 AM

Les méthodes qui peuvent interroger la version Nginx sont: utilisez la commande nginx -v; Afficher la directive de version dans le fichier nginx.conf; Ouvrez la page d'erreur Nginx et affichez le titre de la page.

Comment vérifier si Nginx est démarré Comment vérifier si Nginx est démarré Apr 14, 2025 pm 01:03 PM

Comment confirmer si Nginx est démarré: 1. Utilisez la ligne de commande: SystemCTl Status Nginx (Linux / Unix), netStat -ano | Findstr 80 (Windows); 2. Vérifiez si le port 80 est ouvert; 3. Vérifiez le message de démarrage NGINX dans le journal système; 4. Utilisez des outils tiers, tels que Nagios, Zabbix et Icinga.

Comment vérifier le nom du conteneur Docker Comment vérifier le nom du conteneur Docker Apr 15, 2025 pm 12:21 PM

Vous pouvez interroger le nom du conteneur Docker en suivant les étapes: répertorier tous les conteneurs (Docker PS). Filtrez la liste des conteneurs (à l'aide de la commande grep). Obtient le nom du conteneur (situé dans la colonne "Noms").

Comment exécuter nginx apache Comment exécuter nginx apache Apr 14, 2025 pm 12:33 PM

Pour faire en sorte que Nginx exécute Apache, vous devez: 1. Installez Nginx et Apache; 2. Configurer l'agent Nginx; 3. Démarrer Nginx et Apache; 4. Testez la configuration pour vous assurer que vous pouvez voir le contenu Apache après avoir accédé au nom de domaine. De plus, vous devez faire attention à d'autres questions telles que la correspondance du numéro de port, la configuration de l'hôte virtuel et les paramètres SSL / TLS.

Comment créer un miroir dans Docker Comment créer un miroir dans Docker Apr 15, 2025 am 11:27 AM

Étapes pour créer une image docker: écrivez un dockerfile qui contient les instructions de construction. Créez l'image dans le terminal, en utilisant la commande docker build. Marquez l'image et attribuez des noms et des balises à l'aide de la commande docker tag.

Comment démarrer un conteneur par Docker Comment démarrer un conteneur par Docker Apr 15, 2025 pm 12:27 PM

Étapes de démarrage du conteneur Docker: Tirez l'image du conteneur: Exécutez "Docker Pull [Mirror Name]". Créer un conteneur: utilisez "Docker Create [Options] [Mirror Name] [Commandes et paramètres]". Démarrez le conteneur: exécutez "docker start [nom de conteneur ou id]". Vérifiez l'état du conteneur: vérifiez que le conteneur s'exécute avec "Docker PS".

See all articles