Назад | Перейти на главную страницу

Перенаправление всего трафика на HTTP, кроме одного URL

Я ломал голову, поскольку все форумы говорят, что следующий простой код должен работать для перенаправления всего трафика с 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/ он правильно перенаправляет на Non-SSL http://example.com/ но если я пойду в https://example.com/checkout это говорит

404 Not Found
nginx/1.8.1

Не уверен, что мне здесь не хватает ....

Во-первых, я бы сам такую ​​конфигурацию не делал. Смешав http и https на том же сайте делает https безопасность слабее и подвергает ваш сайт атакам типа "злоумышленник посередине".

Однако здесь должна быть рабочая конфигурация для вас, если вы действительно хотите настроить такую ​​вещь.

Основная проблема в вашей конфигурации - это отсутствие определений PHP для вашего /checkout URI.

Я бы сделал такую ​​конфигурацию. Это также содержит оптимизацию для вашей конфигурации:

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 блок.

Однако могут возникнуть проблемы со ссылками, которые создает Magento, и с тем, как запросы перенаправляются между http и https. Настройки безопасности файлов cookie - это то, что может вызвать проблемы.

Попробуйте это небольшое изменение. ~ * Должен указывать Nginx на то, что регистр не учитывает любой URL-адрес с / checkout / в нем, а не только с точным 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;
    }
}