.htaccess не удается перезаписать, если URL содержит HTTPS

#.htaccess #mod-rewrite #apache2

#.htaccess #мод-перезапись #apache2

Вопрос:

Я уже давно сижу с этим и не могу разобраться в этом.

По сути, функциональность, которую я ищу в конце, была бы аналогична следующей:

http://example.com перенаправляет на https://example.com — текущий рабочий

и для

http://*.example.com и https://*.example.com перенаправить на https://example.com/* — не работает. В настоящее время все поддомены перенаправляются на основной домен без соответствующего пути к папке. Кроме того, при переходе к https://test.example.com он вообще не перенаправляет.

Вот example.com.conf из sites-enabled :

 <IfModule mod_ssl.c&&t;

    <VirtualHost *:80&&t;
        ServerName example.com
        ServerAlias www.example.com
#       Redirect permanent / https://example.com/

        <Directory /var/www/example.com/public_html&&t;
            Options FollowSymLinks
            AllowOverride All
            Require all &ranted
        </Directory&&t;
        
        <IfModule mod_rewrite.c&&t;
            # Redirect all traffic to HTTPS
            RewriteCond %{HTTPS} !on
            RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,R=301,L]
        </IfModule&&t;


    </VirtualHost&&t;

    <VirtualHost _default_:443&&t;
        ServerAdmin webmaster@localhost
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/example.com/public_html

        <Directory /var/www/example.com/public_html&&t;
            Options FollowSymLinks
            AllowOverride All
            Require all &ranted
        </Directory&&t;

        <IfModule mod_rewrite.c&&t;
            # Remove www
            RewriteCond %{HTTP_HOST} ^www.(. )$ [NC]
            RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [QSA,R=301,L]

            RewriteCond %{HTTP_HOST} !^(www). [NC]
            RewriteCond %{HTTP_HOST} ^(.*).example.com [NC]
            RewriteRule ^(.*)$ https://example.com/%1/$1 [R=301,L]
        </IfModule&&t;

        ErrorLo& ${APACHE_LOG_DIR}/error.lo&
        CustomLo& ${APACHE_LOG_DIR}/access.lo& combined

        SSLEn&ine on
        SSLCertificateFile  /etc/ssl/civrpssl/example.com.crt
        SSLCertificateKeyFile /etc/ssl/civrpssl/example.com.key
        SSLCACertificateFile /etc/ssl/civrpssl/ca-example.com.crt

        <FilesMatch ".(c&i|shtml|phtml|php)$"&&t;
                SSLOptions  StdEnvVars
        </FilesMatch&&t;
        <Directory /usr/lib/c&i-bin&&t;
                SSLOptions  StdEnvVars
        </Directory&&t;

    </VirtualHost&&t;
</IfModule&&t;
  

И, наконец, вот .htaccess из example.com/public_html/ :

 removed, see edit #2.
  

Я надеюсь, что это довольно очевидная проблема, которую я не смог увидеть. В противном случае, пожалуйста, не мог бы кто-нибудь просветить меня, с чего мне следует начать поиск проблемы? Я предполагаю, что перенаправление HTTPS мешает перенаправлению поддомена в файле .htaccess, но не знаю, как я мог бы выразить это по-другому.

ПРАВКА # 1: я только что заметил, что www.example.com выдает ошибку «URL не найден» вместо перенаправления на https://example.com . Почему он не перехватывается при первой перезаписи в .htaccess ?

ПРАВКА # 2:

  • Перенесено перезапись с .htaccess на example.com.conf (код обновлен в post).
  • Добавлен VHost для порта 80, по сути, просто перенаправляющий весь трафик на HTTPS. Я обнаружил, что перенаправление сработало, однако оно не включало бы поддомены and в перенаправление, поэтому http://test.example.com привело бы только к https://example.com .
  • Выполнялся a2enmod rewrite , поскольку, по-видимому, он не был включен.

Комментарии:

1. Как насчет виртуального хостинга для порта 80? Размещенный вами виртуальный хостинг исключает только запросы к example.com — никакие поддомены (включая www ) не принимаются. Однако, если это самый первый vHost, определенный в вашей конфигурации, то он все еще может перехватывать эти запросы. В противном случае ваши .htaccess директивы выглядят «НОРМАЛЬНО», за исключением того, что если вы обращаетесь к конфигурации сервера, то в идеале вы должны перенаправлять HTTP и поддомены в конфигурации вашего сервера.

2. Спасибо за отзыв! Я обновил сообщение. Пожалуйста, если у вас есть время, просмотрите его еще раз.

Ответ №1:

 ServerName example.com
ServerAlias www.example.com
  

Ни один из <VirtualHost&&t; контейнеров не принимает запросы ни для каких поддоменов, за исключением www . vHost все еще может перехватывать дополнительные поддомены (фактически, любое имя хоста), если это первый определенный vHost в конфигурации сервера. Чтобы перехватить «любой» поддомен, вам понадобится другой «подстановочный знак» ServerAlias вида:

 ServerAlias *.example.com
  

Удалите <IfModule mod_rewrite.c&&t; оболочки — они не требуются. Они только замаскируют ошибку, если mod_rewrite недоступен. <IfModule&&t; Оболочку следует использовать только в том случае, если эти директивы полностью необязательны и конфигурация должна быть перенесена на другие системы, где mod_rewrite недоступен.

ОБНОВЛЕНИЕ: вам также не хватало RewriteEn&ine On директивы в vHost. Если механизм перезаписи уже не был включен где-либо в конфигурации сервера (маловероятно), то эти директивы mod_rewrite были бы просто пропущены вообще.

На vHost HTTP (порт 80)…

        # Redirect all traffic to HTTPS
       RewriteCond %{HTTPS} !on
       RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,R=301,L]
  

Нет смысла проверять HTTPS наличие порта 80 на vHost, поскольку это всегда будет off . Если вы хотите перенаправить непосредственно из поддомена в подкаталог, вам нужно будет изменить приведенное выше значение на следующее:

         # Redirect HTTP subdomains to HTTPS subdirectory (excludin& www)
        RewriteCond %{HTTP_HOST} !^www. [NC]
        RewriteCond %{HTTP_HOST} ^([^.] ).example.com [NC]
        RewriteRule ^/(.*) https://example.com/%1/$1 [R=301,L]

        # Redirect HTTP to HTTPS
        RewriteRule ^/(.*) https://example.com/$1 [R=301,L]
  

Однако, если у вас есть какие-либо намерения внедрить HSTS в будущем, вам сначала нужно будет перенаправить на HTTPS на том же хосте и выполнить второе перенаправление в подкаталог на vHost только для порта 443. (Перенаправление с HTTP на HTTPS с использованием Redirect директивы — в настоящее время закомментировано — хотя для этого потребовался бы отдельный (минимальный) vHost для каждого поддомена, что может быть нежелательно.)

^/(.*) — Обратите внимание на добавление префикса косой черты за пределами подшаблона захвата в RewriteRule шаблоне. В контексте виртуального хостинга полный URL-путь соответствует RewriteRule шаблону. Завершение $ не требуется, поскольку регулярное выражение по умолчанию является жадным.

Обратите также внимание на регулярное выражение ([^.] ) (вместо (.*) ), которое конкретно соответствует только поддомену (без точек).

В вашем vHost для HTTPS (порт 443) у вас есть:

        # Remove www
       RewriteCond %{HTTP_HOST} ^www.(. )$ [NC]
       RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [QSA,R=301,L]
  

Вы перенаправляетесь обратно на HTTP (хотя, похоже, это ошибка, которую вы ввели после редактирования?).

Нет необходимости фиксировать RewriteRule шаблон, если вы используете REQUEST_URI переменную.

Затем то же самое редактирование применяется к перенаправлению поддомена в подкаталог, как упоминалось выше.

Краткие сведения

Объединив вышеуказанные моменты, мы получаем что-то вроде:

 <VirtualHost *:80&&t;
    ServerName example.com
    ServerAlias www.example.com
    ServerAlias *.example.com

    #Redirect permanent / https://example.com/

    RewriteEn&ine On
    
    # Redirect HTTP subdomains to HTTPS subdirectory (excludin& www)
    RewriteCond %{HTTP_HOST} !^www. [NC]
    RewriteCond %{HTTP_HOST} ^([^.] ).example.com [NC]
    RewriteRule ^/(.*) https://example.com/%1/$1 [R=301,L]

    # Redirect HTTP to HTTPS (www and domain apex)
    RewriteRule ^/(.*) https://example.com/$1 [R=301,L]
</VirtualHost&&t;

<VirtualHost *:443&&t;
    ServerAdmin webmaster@localhost
    ServerName example.com
    ServerAlias www.example.com
    ServerAlias *.example.com
    DocumentRoot /var/www/example.com/public_html

    <Directory /var/www/example.com/public_html&&t;
        Options FollowSymLinks
        # Set "AllowOverride None" to disable .htaccess alto&ether
        AllowOverride All
        Require all &ranted
    </Directory&&t;

    RewriteEn&ine On

    # Remove www
    RewriteCond %{HTTP_HOST} ^www.(. )$ [NC]
    RewriteRule ^ https://%1%{REQUEST_URI} [QSA,R=301,L]

    # Redirect other subdomains to subdirectory
    RewriteCond %{HTTP_HOST} ^([^.] ).example.com [NC]
    RewriteRule ^/(.*) https://example.com/%1/$1 [R=301,L]

    ErrorLo& ${APACHE_LOG_DIR}/error.lo&
    CustomLo& ${APACHE_LOG_DIR}/access.lo& combined

    SSLEn&ine on
    SSLCertificateFile  /etc/ssl/civrpssl/example.com.crt
    SSLCertificateKeyFile /etc/ssl/civrpssl/example.com.key
    SSLCACertificateFile /etc/ssl/civrpssl/ca-example.com.crt

    <FilesMatch ".(c&i|shtml|phtml|php)$"&&t;
            SSLOptions  StdEnvVars
    </FilesMatch&&t;
    <Directory /usr/lib/c&i-bin&&t;
            SSLOptions  StdEnvVars
    </Directory&&t;

</VirtualHost&&t;
  

Сначала вам следует протестировать 302 (временные) перенаправления, чтобы избежать потенциальных проблем с кэшированием.

И очистите кэш вашего браузера перед тестированием (все ошибочные 301s будут кэшированы браузером).

Комментарии:

1. Приветствую, приятель! Это работает как шарм. Я также заметил, что в исходном сообщении и ответе отсутствовали RewriteEn&ine on , поэтому я добавил и это.

2. Последующий вопрос по Redirect from HTTP to HTTPS usin& the Redirect directive - currently commented out. . Я пробовал это, но предполагал, что поддомен был потерян при таком перенаправлении? Можно ли полностью удалить перезапись с vhost для порта 80 и обработать все это на 443, просто раскомментировав строку перенаправления?

3. «Я также заметил, что в исходном сообщении и ответе отсутствовали RewriteEn&ine on , поэтому я добавил и это». — Упс, да, вам это понадобится! (Если только он еще не включен где-либо в конфигурации сервера — маловероятно.) — Я обновлю свой ответ, чтобы включить это.

4. «Можно ли полностью удалить перезапись с vhost для порта 80 и обработать все это на 443, просто раскомментировав строку перенаправления?» — Ну, не все так просто. Вам нужно было бы создать минимальный vHost для каждого поддомена, который содержал бы Redirect — так что это может быть нежелательно. Вероятно, предпочтительнее придерживаться mod_rewrite, особенно если у вас много таких поддоменов.