2008-09-17 24 views
113

Mam tylko jedną stronę, którą chcę wymusić, aby uzyskać dostęp do strony HTTPS (PHP na Apache). Jak to zrobić, nie powodując, że cały katalog wymaga HTTPS? Lub, jeśli przesyłasz formularz do strony HTTPS ze strony HTTP, czy wysyła on formularz przez HTTPS zamiast HTTP?Jak zmusić użytkowników do uzyskiwania dostępu do mojej strony przez HTTPS zamiast HTTP?

Oto mój przykład:

http://www.example.com/some-page.php 

chcę go mieć dostęp wyłącznie poprzez:

https://www.example.com/some-page.php 

Jasne, mogę umieścić wszystkie linki do tej strony wskazał w wersji HTTPS, ale to nie powstrzyma niektórych głupców od uzyskania dostępu do niego przez HTTP celowo ...

Jedną z rzeczy, które myślałem było umieszczenie przekierowania w nagłówku pliku PHP, aby sprawdzić, czy są one dostępne g wersja HTTPS:

if($_SERVER["SCRIPT_URI"] == "http://www.example.com/some-page.php"){ 
    header('Location: https://www.example.com/some-page.php'); 
} 

Ale to nie może być właściwa droga, prawda?

BTW, nie zwracaj uwagi na URL. Wiem, że gdyby to była strona, na której był koszyk na zakupy itp., Robiłbyś to w inny sposób. Potraktuj to jako stronę z witryny, która sprzedaje jeden przedmiot za jedną cenę, gdzie wpisujesz informacje o karcie kredytowej, aby wysłać je do bramki płatniczej w witrynie zewnętrznej w celu jednorazowego obciążenia karty.

+0

możliwy duplikat [Wymuś użycie SSL/https przy użyciu .htaccess i mod \ _rewrite] (http://stackoverflow.com/questions/4398951/force-ssl-https-using-htaccess-and-mod-rewrite) – Trilarion

+1

Czy są jakieś dlaczego nie potrzebujesz tylko SSL dla wszystkich stron? –

Odpowiedz

44

Można zrobić to z dyrektywy i mod_rewrite w Apache:

<Location /buyCrap.php> 
RewriteEngine On 
RewriteCond %{HTTPS} off 
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} 
</Location> 

Można uczynić Lokalizacja mądrzejszy upływem czasu stosując regular expressions jeśli chcesz.

+6

Gdzie to umieścisz? plik .htaccess? –

+1

Czy REQUEST_URI nie zawiera "ciągu zapytania" (np.? Page = 1 & id = 41 itd.)? Tak mówi dokumentacja Apache'a ... Więc jeśli spróbuję uzyskać dostęp do http://site.com/index.php?page=1&id=12 zostanie przekierowany https://site.com/index.php – Rolf

+2

From apache Documentation: REQUEST_URI Składnik ścieżki żądanego URI, na przykład "/index.html". W szczególności wyklucza to ciąg zapytania, który jest dostępny jako jego własna zmienna o nazwie QUERY_STRING. Musisz więc dodać QUERY_STRING po REQUEST_URI – Rolf

3

Użyj $_SERVER['HTTPS'], aby powiedzieć, czy jest to SSL, i przekieruj do odpowiedniego miejsca, jeśli nie.

Pamiętaj, że strona wyświetlająca formularz nie musi być podawana za pośrednictwem protokołu HTTPS, jest to adres URL, który najbardziej go potrzebuje.

Edycja: tak, jak wskazano poniżej, najlepiej jest mieć cały proces w HTTPS. O wiele bardziej pocieszające - wskazywałem, że post jest najbardziej krytyczną częścią. Należy również zadbać o to, aby wszelkie pliki cookie były bezpieczne, dlatego będą wysyłane tylko przez SSL. Rozwiązanie mod_rewrite jest również bardzo dobre, użyłem go do zabezpieczenia wielu aplikacji na mojej własnej stronie.

+0

To prawda, że ​​sam formularz nie musi być https, chociaż jest to dobry pomysł większość ludzi, którzy o tym nie wiedzą. Jeśli mają zamiar przesłać formularz i zauważyć, że ikona kłódki nie istnieje, mogą błędnie założyć, że formularz jest niezabezpieczony. –

+1

@ Graeme: dodatkowo nikt nie może być przekonany, że formularz zostanie kiedykolwiek wysłany przez https. Cała forma (wyświetlana przez http) może być fałszywa, zgłaszana do nieznanej strony lub strony z tekstem jawnym http. Https to nie tylko szyfrowanie, ale także uwierzytelnianie serwera. –

150

Sposób Robiłem to wcześniej jest w zasadzie jak to, co napisałeś, ale nie ma żadnych wartości jawnie wpisanej:

if($_SERVER["HTTPS"] != "on") 
{ 
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]); 
    exit(); 
}
+14

Nie pamiętasz, aby wywołać metodę exit(), aby skrypt przestał działać po przekierowaniu. Zazwyczaj zawijam to w funkcję o nazwie requireSSL(). Mogę to nazwać na górze każdej strony, którą chcę zaszyfrować. –

+24

Zmień, czy ma być '(pusty ($ _ SERVER [" HTTPS "]) || $ _SERVER [" HTTPS "]! ==" on ")', aby naprawić powiadomienia PHP. – dave1010

+0

Czy zmienne/podatne na interwencje użytkowników nie są zmiennymi '$ _SERVER []'? –

1

Nie mieszać HTTP i HTTPS na tej samej stronie. Jeśli masz stronę formularza, która jest obsługiwana za pośrednictwem protokołu HTTP, będę denerwować się przesyłaniem danych - nie widzę, czy zgłoszenie przechodzi przez HTTPS lub HTTP bez robienia źródła widoku i polowania na niego.

Obsługa formularza za pomocą protokołu HTTPS wraz z linkiem do przesyłania nie stanowi dużej zmiany dla korzyści.

0

Powinieneś nie ze względów bezpieczeństwa. Zwłaszcza, jeśli w grze są pliki cookie. Pozostawia cię szeroko otwartymi na ataki oparte na plikach cookie.

W obu przypadkach należy użyć reguł kontroli Apache, aby ją dostroić.

Następnie można sprawdzić, czy protokół HTTPS jest włączony i, w razie potrzeby, przekierować w razie potrzeby.

Powinieneś przekierować na stronę płatności tylko za pomocą FORM POST (bez pobierania), , a dostęp do strony bez POST powinien zostać przekierowany na inne strony. (To złapie ludzi po prostu gorąco skoków.)

http://joseph.randomnetworks.com/archives/2004/07/22/redirect-to-ssl-using-apaches-htaccess/

jest dobrym miejscem do rozpoczęcia, przeprosiny za nie więcej. Ale naprawdę musisz powinien przerzucić wszystko przez SSL.

Jest nadopiekuńczy, ale przynajmniej masz mniej zmartwień.

8
// Force HTTPS for security 
if($_SERVER["HTTPS"] != "on") { 
    $pageURL = "Location: https://"; 
    if ($_SERVER["SERVER_PORT"] != "80") { 
     $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"]; 
    } else { 
     $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"]; 
    } 
    header($pageURL); 
} 
35

Należy wymusić klienta żądania HTTPS zawsze z HTTP Strict Transport Security (TGV) nagłówkami:

// Use HTTP Strict Transport Security to force client to use secure connections only 
$use_sts = true; 

// iis sets HTTPS to 'off' for non-SSL requests 
if ($use_sts && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') { 
    header('Strict-Transport-Security: max-age=31536000'); 
} elseif ($use_sts) { 
    header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301); 
    // we are in cleartext at the moment, prevent further execution and output 
    die(); 
} 

Należy pamiętać, że TGV jest obsługiwana w większości nowoczesnych przeglądarek, ale nie powszechne. Tak więc powyższa logika przekierowuje użytkownika niezależnie od obsługi, jeśli kończy się na HTTP, a następnie ustawia nagłówek HSTS, aby dalsze żądania klientów były przekierowywane przez przeglądarkę, jeśli to możliwe.

+0

Jestem zaskoczony, że inne odpowiedzi nie obejmują tego nagłówka, to jest dość ważne ... jakiekolwiek pułapki na połączenie dwóch z nich? – keisar

+0

Nie ... możesz zdecydowanie ustawić ten nagłówek, jeśli chcesz zawsze korzystać z HTTPS. Po prostu redundantne jest ustawienie go przed i po wykonaniu przekierowania. Zmieniłem również powyższą odpowiedź, aby dokładniej wyjaśnić zgodność. –

+1

(Redagowanie oryginalnego komentarza) Nie zauważyłem konkretnego wymogu "tylko jednej strony". HSTS będzie mieć zastosowanie do wszystkich stron; moja odpowiedź jest technicznie niepoprawna. –

5

http://www.besthostratings.com/articles/force-ssl-htaccess.html

Czasami może być konieczne, aby upewnić się, że użytkownik przegląda witrynę ponad związku securte. Łatwym w sposób zawsze przekierować użytkownika do bezpiecznego połączenia (https: //) można wykonać za pomocą pliku .htaccess zawierający następujące wiersze:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://www.example.com/$1 [R,L] 

Proszę pamiętać, że .htaccess powinien znajdować się w główny folder strony internetowej.

W przypadku, gdy chcesz, aby wymusić HTTPS dla danego folderu można użyć:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteCond %{REQUEST_URI} somefolder 
RewriteRule ^(.*)$ https://www.domain.com/somefolder/$1 [R,L] 

Plik .htaccess powinny być umieszczone w folderze, w którym trzeba wymusić HTTPS.

-3
<?php 
// Require https 
if ($_SERVER['HTTPS'] != "on") { 
    $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; 
    header("Location: $url"); 
    exit; 
} 
?> 

To proste.

+1

powielona odpowiedź –

6

Musiałem zrobić coś takiego, kiedy pracuję z systemem równoważenia obciążenia. Kapelusz wskazówka https://stackoverflow.com/a/16076965/766172

function isSecure() { 
    return (
     (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') 
    || $_SERVER['SERVER_PORT'] == 443 
    || (
      (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') 
     || (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') 
     ) 
    ); 
} 

function requireHTTPS() { 
    if (!isSecure()) { 
     header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], TRUE, 301); 
     exit; 
    } 
} 
4

Ok .. Teraz jest mnóstwo rzeczy na to teraz, ale tak naprawdę nikt nie dopełnia pytanie „bezpieczne”. Dla mnie jest to skrupulatne w użyciu czegoś, co jest niepewne.

O ile nie używasz go jako przynęty.

Propagacja $ _SERVER może być zmieniana na życzenie kogoś, kto wie jak.

Również Sazzad Tushar Khan i thebigjc oświadczyli, że możesz również użyć httccess, aby to zrobić i jest tam wiele odpowiedzi, które go zawierają.

Wystarczy dodać:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://example.com/$1 [R,L] 

do końca co masz w .httaccess i ów, że.

Nadal nie jesteśmy tak bezpieczni, jak tylko możemy być przy tych 2 narzędziach.

Reszta jest prosta. Jeśli nie brakuje atrybutów tj ...

if(empty($_SERVER["HTTPS"])){ // SOMETHING IS FISHY 
} 

if(strstr($_SERVER['HTTP_HOST'],"mywebsite.com") === FALSE){// Something is FISHY 
} 


powiedzieć także zaktualizowaniu pliku httaccess i sprawdzić:

if($_SERVER["HTTPS"] !== "on"){// Something is fishy 
} 

Istnieje wiele więcej zmiennych można sprawdzić tj ..

HOST_URI(Jeśli istnieją statyczne atrybuty o tym do sprawdzenia)

HTTP_USER_AGENT(różne wartości tej samej sesji)

Więc Im powiedzenie to nie tylko godzić się na jednej lub drugiej, gdy odpowiedź leży w kombinacji.

Więcej httaccess przepisywania informacji patrz docs->http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

stosy tutaj ->Force SSL/https using .htaccess and mod_rewrite
i
Getting the full URL of the current page (PHP)
aby wymienić tylko kilka.

+2

, ale teraz pojawia się następujący błąd: 'ERR_TOO_MANY_REDIRECTS'. Jak to naprawić? – Pathros

11

I właśnie utworzony plik .htaccess i dodał:

RewriteEngine On 
RewriteCond %{HTTPS} off 
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} 

Simple!

-1

Użyłem tego skryptu i działa on dobrze na stronie.

if(empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "off"){ 
    $redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; 
    enter code hereheader('HTTP/1.1 301 Moved Permanently'); 
    header('Location: ' . $redirect); 
    exit(); 
} 
0

Jeśli używasz Apache lub czegoś w rodzaju LiteSpeed, który obsługuje pliki .htaccess, możesz wykonać następujące czynności. Jeśli nie masz jeszcze pliku .htaccess, powinieneś utworzyć nowy plik .htaccess w swoim katalogu głównym (zwykle tam, gdzie znajduje się twój index.php). Teraz dodaj te linie jako pierwszych zasad przepisywania w swojej .htaccess:

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

Trzeba tylko dyspozycję „RewriteEngine On” raz w .htaccess dla wszystkich reguł przepisywania, więc jeśli masz już go po prostu skopiować druga i trzecia linia.

Mam nadzieję, że to pomoże.

+1

Proszę wyjaśnić, co się stało, przypadkowy nieznajomy w Internecie. –

+0

To jest to, co zadziałało dla mnie i co używam w moich własnych skryptach na Zend 2-like Framework - Nie rozumiem upadku. – Antonio

+0

Być może zostałeś odrzucony, ponieważ odpowiedź jest praktycznie taka sama jak [this] (http://stackoverflow.com/a/31000510/1697459) z @MatHatrik, który został opublikowany ponad rok wcześniej? – Wilt

1

Stosując to nie wystarczy:

if($_SERVER["HTTPS"] != "on") 
{ 
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]); 
    exit(); 
} 

Jeśli masz żadnych treści http (jak http zewnętrznego źródła obrazu), przeglądarka wykryje potencjalne zagrożenie. Więc pamiętaj wszystkie swoje ref i src wewnątrz kodu są https

0

Byłem przez wiele rozwiązań ze sprawdzania stanu $ _SERVER [HTTPS] ale wydaje się, że nie jest wiarygodne, ponieważ czasami nie ustawia lub ustawić włączać, wyłączać itp., powodując przekierowanie do pętli wewnętrznej.

Oto najbardziej niezawodne rozwiązanie, jeśli serwer obsługuje $ _SERVER [SCRIPT_URI]

if (stripos(substr($_SERVER[SCRIPT_URI], 0, 5), "https") === false) { 
    header("location:https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"); 
    echo "<meta http-equiv='refresh' content='0; url=https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]'>"; 
    exit; 
} 

Należy pamiętać, że w zależności od instalacji, serwer może nie wspierać $ _SERVER [SCRIPT_URI], ale jeśli to robi , jest to lepszy skrypt do użycia.

można sprawdzić tutaj: Why do some PHP installations have $_SERVER['SCRIPT_URI'] and others not

1

dla osób korzystających IIS Dodanie tej linii w pliku web.config pomogą:

<httpProtocol> 
    <customHeaders> 
     <add name="Strict-Transport-Security" value="max-age=31536000"/> 
    </customHeaders> 
</httpProtocol> 
<rewrite> 
    <rules> 
     <rule name="HTTP to HTTPS redirect" stopProcessing="true"> 
       <match url="(.*)" /> 
       <conditions> 
       <add input="{HTTPS}" pattern="off" ignoreCase="true" /> 
       </conditions> 
       <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" /> 
     </rule> 
    </rules> 
</rewrite> 

pełny przykładowy plik

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <system.webServer> 
     <httpProtocol> 
      <customHeaders> 
       <add name="Strict-Transport-Security" value="max-age=31536000"/> 
      </customHeaders> 
     </httpProtocol> 
     <rewrite> 
      <rules> 
       <rule name="HTTP to HTTPS redirect" stopProcessing="true"> 
         <match url="(.*)" /> 
         <conditions> 
         <add input="{HTTPS}" pattern="off" ignoreCase="true" /> 
         </conditions> 
         <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" /> 
       </rule> 
      </rules> 
     </rewrite> 
    </system.webServer> 
</configuration> 
+0

Pytanie dotyczy w szczególności Apache, a nie IIS. – Quentin

+0

A) nie otagowano apache. Apache jest metioned między cytatami. B) jest to ogólne pytanie, które nie ma nic wspólnego z apache w ogóle. Ma zastosowanie do wielu serwerów internetowych obsługujących php – Tschallacka

2

korzystanie htaccess:

#if domain has www. and not https:// 
    RewriteCond %{HTTPS} =off [NC] 
    RewriteCond %{HTTP_HOST} ^(?i:www+\.+[^.]+\.+[^.]+)$ 
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307] 

#if domain has not www. 
    RewriteCond %{HTTP_HOST} ^([^.]+\.+[^.]+)$ 
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307]