将所有stream量redirect到除一个URL之外的HTTP

我一直在挠头,因为所有的论坛都说,以下简单的代码应该工作,redirect所有stream量从HTTPS到HTTP,除了一个位置( Nginx的:在一个path上强制SSL,其他人不SSL ),但在我的情况它没有按预期工作

这是Magento网站有以下nginxconfiguration

upstream examplecombackend { server unix:/var/run/php-fcgi-examplecom.sock; } server { listen 111.11.111.111:80; server_name example.com *.example.com; access_log /home/www/vhosts/example.com/logs/access.log; error_log /home/www/vhosts/example.com/logs/error.log; root /home/www/vhosts/example.com/httpdocs; location / { index index.html index.php; try_files $uri $uri/ @handler; expires 30d; } location /checkout/ { rewrite ^ https://$host$request_uri? permanent; } location @handler { rewrite / /index.php; } location ~ .php/ { rewrite ^(.*.php)/ $1 last; } location ~ .php$ { if (!-e $request_filename) { rewrite / /index.php last; } expires off; fastcgi_pass examplecombackend; fastcgi_param HTTPS $fastcgi_https; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } server { listen 111.11.111.111:443 ssl; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; server_name example.com *.example.com; root /home/www/vhosts/example.com/httpdocs; location / { rewrite ^ http://$host$request_uri? permanent; } location /checkout/ { } } 

现在,当我进入SSL https://example.com/时,它正确地转发到非SSL http://example.com/,但如果我去https://example.com/checkout它说

 404 Not Found nginx/1.8.1 

不知道我在这里失踪….

首先,我不会自己做这样的configuration。 在同一个网站上混合使用httphttps会使https安全性变弱,并使您的网站遭受中间人攻击。

但是,如果你真的想要设置这样的事情,这里应该是一个工作configuration。

您configuration中的主要问题是您的/checkout URI缺lessPHP的定义。

我会做这样的configuration。 这还包含对您的configuration的优化:

 upstream examplecombackend { server unix:/var/run/php-fcgi-examplecom.sock; } server { listen 111.11.111.111:80; server_name example.com *.example.com; access_log /home/www/vhosts/example.com/logs/access.log; error_log /home/www/vhosts/example.com/logs/error.log; root /home/www/vhosts/example.com/httpdocs; location / { index index.html index.php; try_files $uri $uri/ /index.php; expires 30d; } location /checkout { rewrite ^ https://$host$request_uri? permanent; } location ~ (.+\.php)/ { rewrite ^ $1 last; } location ~ \.php$ { expires off; fastcgi_pass examplecombackend; fastcgi_param HTTPS $fastcgi_https; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } server { listen 111.11.111.111:443 ssl; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; server_name example.com *.example.com; root /home/www/vhosts/example.com/httpdocs; location /checkout { rewrite ^ /index.php; } location ~ \.php$ { expires off; fastcgi_pass examplecombackend; fastcgi_param HTTPS $fastcgi_https; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location / { rewrite ^ http://$host$request_uri? permanent; } } 

我做的更改:

 location / { index index.html index.php; try_files $uri $uri/ /index.php; expires 30d; } 

我删除了@handler位置,因为它与index.phptry_files指令的最后一个元素相同。

 location ~ .php/ { rewrite ^(.*.php)/ $1 last; } 

我改变了正则expression式的捕获发生在location级别,因此在匹配这个位置的每个请求上只有一个正则expression式的匹配less了,因为我们可以使用简单的^作为rewrite指令中的匹配条件。

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

我添加了反斜杠转义location正则expression式的条件,因为没有反斜杠它将匹配例如/path/to/aphp ,因为. 自己匹配任何字符。

我还从块中删除了上面显示的iftesting,因为之前在try_files指令中已经发生过相同的testing。

最后,解决您的实际问题:

在你的https server块,我改变了这样的location块:

  location /checkout { rewrite ^ /index.php; } location ~ \.php$ { expires off; fastcgi_pass examplecombackend; fastcgi_param HTTPS $fastcgi_https; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } 

所以, location /checkout块告诉nginx重写所有的请求到/index.php ,就像在http服务器块一样。 此外,PHP处理locationhttp块中的location相同。

但是,Magento创build的链接仍然可能存在问题,并且请求会在httphttps之间redirect。 Cookie安全设置是一件可能导致问题的事情。

试试这个小小的变化。 〜*应该告诉Nginx不区分大小写匹配任何带有/ checkout /的URL,而不仅仅是准确的URL / checkout /。

我有点生疏,我不记得确切的位置匹配顺序和语法,但值得一试。

 location ~* /checkout/ { 

有条件的重写可能有助于你的情况:

 server { listen 111.11.111.111:80; listen 111.11.111.111:443 ssl; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; server_name example.com *.example.com; access_log /home/www/vhosts/example.com/logs/access.log; error_log /home/www/vhosts/example.com/logs/error.log; root /home/www/vhosts/example.com/httpdocs; location / { if ($scheme = "https") { return 301 http://$server_name$request_uri; break; } index index.html index.php; try_files $uri $uri/ @handler; expires 30d; } location /checkout/ { if ($scheme = "http") { return 301 https://$server_name$request_uri; break; } } location @handler { rewrite / /index.php; } location ~ .php/ { rewrite ^(.*.php)/ $1 last; } location ~ .php$ { if (!-e $request_filename) { rewrite / /index.php last; } expires off; fastcgi_pass examplecombackend; fastcgi_param HTTPS $fastcgi_https; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }