Примушуйте SSL / https за допомогою .htaccess та mod_rewrite


Відповіді:


438

Для Apache ви можете використовувати mod_sslдля примусового використання SSL за допомогою SSLRequireSSL Directive:

Ця директива забороняє доступ, якщо для поточного з'єднання не ввімкнено протокол HTTP через SSL (тобто HTTPS). Це дуже зручно всередині віртуального хоста або підтримуваних SSL програм для захисту від помилок конфігурації, які викривають речі, які слід захистити. Коли ця директива присутня, всі запити відмовляються, які не використовують SSL.

Це не зробить переспрямування на https. Щоб перенаправити, спробуйте наступне mod_rewriteу вашому файлі .htaccess

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

або будь-який з різних підходів, наведених у

Ви також можете вирішити це в межах PHP у випадку, якщо ваш провайдер відключив .htaccess (що малоймовірне, оскільки ви просили цього, але все одно)

if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    if(!headers_sent()) {
        header("Status: 301 Moved Permanently");
        header(sprintf(
            'Location: https://%s%s',
            $_SERVER['HTTP_HOST'],
            $_SERVER['REQUEST_URI']
        ));
        exit();
    }
}

1
Це чудово в нашій ситуації, оскільки в даний час ми маємо суміш трафіку http та https. Для нашої адміністративної області ми просто з’явились у сценарії .htaccess, зберігаючи решту сайту http.
Майкл Дж. Калкінс

1
Коли я використовую метод mod_rewrite, мене надсилають до https, але з помилкою "Сторінка не перенаправляється належним чином".
Czechnology

11
Подальше: Якщо у вас виникають подібні проблеми, перевірте змінні сервера та HTTP. Якщо ваш сервер використовує проксі, ви можете використовувати %{HTTP:X-Forwarded-Proto}або %{HTTP:X-Real-Port}змінні, щоб перевірити, чи включений SSL.
Czechnology

8
Якщо у вас виникають петлі переадресації на серверах, що працюють за проксі-сервера ( CloudFlare , Openshift ), див. Цю відповідь для рішення, яке працює і для цього випадку.
raphinesse

4
@GTodorov - Видалення пробілу зламало переписку для мене. З мого (обмеженого) знання переписувачів, синтаксис є RewriteRule <input-pattern> <output-url>. Таким чином, простір повинен бути там, і сингл ^просто говорить "відповідати всім вхідним URL-адресам".
Sphinxxx

54

Я знайшов mod_rewriteрішення, яке добре працює як для проксі-серверів, так і для непроксі-серверів.

Якщо ви використовуєте CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift або будь-яке інше рішення Cloud / PaaS, і у вас виникають петлі переадресації із звичайними HTTPS переспрямованими, скористайтеся наступним фрагментом.

RewriteEngine On

# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on

# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Це геніальний THX! Але, можливо, потрібно додати умову публікації? RewriteCond% {REQUEST_METHOD}! ^ POST $
Олексій

@Aleksej Щоправда, це порушує незашифровані POST-запити. Але я думаю, що це гарна річ. Таким чином, люди помітять, що роблять щось не так. Я думаю, що найкраще було б перенаправити їх на сторінку, яка інформує їх про те, як правильно користуватися вашою послугою.
raphinesse

@raphinesse Чи знаєте ви відповідь на це запитання: stackoverflow.com/questions/51951082/…
RRN

36

PHP Рішення

Позичаючись безпосередньо з дуже вичерпної відповіді Гордона, зауважу, що ваше запитання зазначає специфіку сторінки, примушуючи HTTPS / SSL-з'єднання.

function forceHTTPS(){
  $httpsURL = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  if( count( $_POST )>0 )
    die( 'Page should be accessed with HTTPS, but a POST Submission has been sent here. Adjust the form to point to '.$httpsURL );
  if( !isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS']!=='on' ){
    if( !headers_sent() ){
      header( "Status: 301 Moved Permanently" );
      header( "Location: $httpsURL" );
      exit();
    }else{
      die( '<script type="javascript">document.location.href="'.$httpsURL.'";</script>' );
    }
  }
}

Потім, як можна ближче до верхньої частини цих сторінок, які ви хочете змусити з’єднати через PHP, ви можете require()централізований файл, що містить цю (та будь-які інші) спеціальні функції, а потім просто запустити forceHTTPS()функцію.

HTACCESS / mod_rewrite Рішення

Я не реалізував подібне рішення особисто (я схильний використовувати рішення PHP, як те, що вище, для простоти), але наступне може бути, принаймні, хорошим початком.

RewriteEngine on

# Check for POST Submission
RewriteCond %{REQUEST_METHOD} !^POST$

# Forcing HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# Forcing HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

з цікавості, навіщо RewriteCond %{REQUEST_METHOD} !^POST$?
депуло

12
Оскільки параметри POST не зберігаються при переадресації. Ви можете опустити цей рядок, якщо хочете переконатися, що всі подання POST захищені (будь-які незахищені публікації POST будуть ігноровані).
Люк Стівенсон

@Lucanos - Як написати RewriteCond, який не примушує переадресацію ні на http, ні на https, коли POST? Мій .htaccess змушує HTTPS на певні конкретні сторінки, а потім змушує HTTP на інші. Однак на сторінках HTTPS є форми, які надсилаються до мого веб-кореня. Форма визначає URL-адресу дії як HTTPS. Однак, оскільки веб-корінь не є однією із тих сторінок, які визначені для примусового використання HTTPS, мій .htaccess примушує переадресувати - а це означає, що змінні POST втрачаються. Як запобігти переадресації на POST?
StackOverflowNewbie

1
@StackOverflowNewbie: Рядок RewriteCond %{REQUEST_METHOD} !^POST$повинен запобігати впливу цих переспрямувань на подання POST.
Люк Стівенсон

Мені подобається ця версія PHP. Це набагато краще, оскільки він вважає POST і обробляє краще, якщо заголовки вже надіслані.
TheStoryCoder

10

Рішення на основі мод-переписування:

Використовуючи наступний код у htaccess, автоматично пересилає всі http-запити до https.

RewriteEngine on

RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Це перенаправить ваші не-www та www http-запити на www- версію https.

Інше рішення (Apache 2.4 *)

RewriteEngine on

RewriteCond %{REQUEST_SCHEME}::%{HTTP_HOST} ^http::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Це не працює на нижчих версіях apache, оскільки змінна% {REQUEST_SCHEME} додана до мод-переписати з 2.4.


9

Я просто хотів би зазначити, що Apache має найгірші правила успадкування при використанні декількох файлів .htaccess на глибинах каталогу. Дві ключові підводні камені:

  • Тільки правила, що містяться у найглибшому .htaccess-файлі, будуть виконуватися за замовчуванням. Ви повинні вказати RewriteOptions InheritDownBeforeдирективу (або подібну), щоб змінити це. (див. питання)
  • Шаблон застосовується до файлового шляху відносно підкаталогу, а не до верхнього каталогу, що містить файл .htaccess із заданим правилом. (див. обговорення)

Це означає , що пропоноване глобальне рішення на Apache Wiki це НЕ буде працювати , якщо ви використовуєте які - або інші файли .htaccess в підкаталогах. Я написав модифіковану версію, яка:

RewriteEngine On
# This will enable the Rewrite capabilities

RewriteOptions InheritDownBefore
# This prevents the rule from being overrided by .htaccess files in subdirectories.

RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [QSA,R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e.  http://www.example.com/foo/ to https://www.example.com/foo/

0

Просто та легко, просто додайте наступне

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Це в значній мірі те, що люди в Інтернеті говорять вам зробити для примусового https. Однак щоразу, коли я це роблю, весь мій веб-сайт стає ЗАБОРОНЕНО або у вас немає дозволу на перегляд. щось таке ... Що я роблю неправильно? Я просто хочу знати, чи маєте ви якусь ідею, перш ніж надсилати питання з цього приводу.
ТН

У мене була подібна проблема, і мені довелося застосувати правила до файлу https.conf. Дивіться мою відповідь нижче.
Risteard

-1

Цей код працює для мене

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

-1

Простий:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.example\.com)(:80)? [NC]
RewriteRule ^(.*) https://example.com/$1 [R=301,L]
order deny,allow

замініть URL-адресу на example.com


НЕМАЄ! URL-адреса сайту повинна бути динамічною.
Амір Саванд

-1

просто змусивши SSL за допомогою Apache .htaccess можна використовувати

SSLOptions +StrictRequire
SSLRequireSSL

для перенаправлення наведена відповідь правильна


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.