我一直很困惑,因为所有的论坛都说,下面的简单代码应该可以将所有流量从 HTTPS 重定向到 HTTP,除了一个位置(Nginx:强制在一个路径上使用 SSL,在其他路径上使用非 SSL)但就我而言,它没有按预期工作
这是 Magento 网站,具有以下 nginx 配置
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/它正确地转发到非 SSLhttp://example.com/但如果我去https://example.com/checkout它说
404 Not Found
nginx/1.8.1
不确定我在这里遗漏了什么......
答案1
首先,我不会自己做这样的配置。在同一个网站上混合使用会使http
安全性变弱,并使你的网站面临中间人攻击。https
https
然而,如果您确实想要设置这样的东西,这里应该有一个适合您的工作配置。
您的配置中的主要问题是缺少 URI 的 PHP 定义/checkout
。
我会进行如下配置。这还包含针对您的配置的优化:
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.php
try_files
location ~ .php/ {
rewrite ^(.*.php)/ $1 last;
}
我改变了正则表达式捕获以使其在级别上发生location
,因此在与此位置匹配的每个请求中发生的正则表达式匹配会少一个,因为我们可以^
在指令中使用简单作为匹配条件rewrite
。
location ~ \.php$ {
if (!-e $request_filename) {
rewrite / /index.php last;
}
我在location
正则表达式条件中添加了反斜杠转义符,因为如果没有反斜杠,它就会匹配,例如/path/to/aphp
,因为.
它本身可以匹配任何字符。
我还if
从块中删除了上面显示的测试,因为相同的测试已经在try_files
之前的指令中发生了。
最后,解决您的实际问题:
在您的server
https 块中,我更改了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 处理location
与块中的相同http
。
http
但是,Magento 创建的链接以及在和之间重定向请求的方式可能仍然存在问题https
。Cookie 安全设置是可能导致问题的因素之一。
答案2
尝试一下这个小改动。~* 应该告诉 Nginx 不区分大小写地匹配任何包含 /checkout/ 的 URL,而不仅仅是精确的 URL /checkout/。
我有点生疏,记不清精确的位置匹配顺序和语法,但值得尝试。
location ~* /checkout/ {
答案3
条件重写可能对你的情况有帮助:
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;
}
}