Kullanıcıları HTTP yerine HTTPS üzerinden sayfama erişmeye nasıl zorlayabilirim?


137

Bir HTTPS sayfası (Apache PHP) olarak erişilmesini zorlamak istiyorum sadece bir sayfa var. Tüm dizini HTTPS gerektirmeden nasıl yapabilirim? Veya bir HTTP sayfasından HTTPS sayfasına bir form gönderirseniz, HTTP yerine HTTPS ile gönderir mi?

İşte benim örnek:

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

Ben sadece üzerinden erişilebilir olmasını istiyorum:

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

Tabii, HTTPS sürümüne işaret eden bu sayfaya giden tüm bağlantıları koyabilirim, ancak bu, bazı aptalların bilerek HTTP üzerinden erişmesini engellemez ...

Düşündüğüm bir şey, HTTPS sürümüne eriştiklerinden emin olmak için PHP dosyasının başlığına bir yönlendirme koymaktı:

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

Ama bu doğru yol olamaz, değil mi?



3
Tüm sayfalar için yalnızca SSL istememenizin bir nedeni var mı?
Tahaan

Yanıtlar:


177

Daha önce yaptığım gibi, yazdıklarınız gibidir, ancak sabit kodlanmış değerleri yoktur:

eğer ($ _ SERVER ["HTTPS"]! = "açık")
{
    başlık ("Konum: https: //". $ _SERVER ["HTTP_HOST"]. $ _SERVER ["REQUEST_URI"]);
    çıkış();
}

15
Komut dosyasının yeniden yönlendirmeden sonra çıkmasını sağlamak için exit () öğesini çağırmayı unuttunuz. Genellikle requirSSL () adlı bir işlevde sarın. Bunu şifrelenmesini istediğim herhangi bir sayfanın üst kısmında arayabilirim.
Jesse Weigert

31
(empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on")PHP bildirimlerini düzeltmek için ise değiştirin .
dave1010

$_SERVER[]Değişkenler kullanıcıların müdahalesine karşı değiştirilebilir / savunmasız değil mi ?
Arian Faurtosh

@ArianFaurtosh kaynağı?
John

3
@ArianFaurtosh bazıları istemci başlıklarından ayıklanır HTTP_X_FORWARDEDve değiştirilebilir, ancak diğerleri doğrudan web sunucusundan hoşlanır HTTPSveya SERVER_PORTayarlanır ve genellikle güvenli olmalıdır .
Mahn

46

Apache'de bir yönerge ve mod_rewrite ile yapabilirsiniz:

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

İsterseniz, yeri düzenli ifadeler kullanarak zaman içinde daha akıllı hale getirebilirsiniz .


6
Bunu nereye koyardın? .htaccess dosyası?

1
REQUEST_URI "sorgu dizesini" içermiyor mu (gibi? Page = 1 & id = 41 vb.)? Apache belgeleri ... ne diyor İşte en Yani erişmeye çalışırsanız site.com/index.php?page=1&id=12 ben yönlendirilecek site.com/index.php
Rolf

2
Apache'den Documentation: REQUEST_URI İstenen URI'nin "/index.html" gibi yol bileşeni. Bu, QUERY_STRING adlı kendi değişkeni olarak kullanılabilen sorgu dizesini özellikle hariç tutar. Dolayısıyla, REQUEST_URI
Rolf

2
Ayrıca yönlendirmek için [R] flagesini eklemeniz gerekir
Rolf

40

İstemciyi her zaman HTTP Sıkı Aktarım Güvenliği (HSTS) başlıklarıyla HTTPS istemeye zorlamalısınız :

// 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();
}

HSTS'nin çoğu modern tarayıcıda desteklendiğini, ancak evrensel olarak desteklenmediğini lütfen unutmayın. Bu nedenle, yukarıdaki mantık, HTTP ile sonuçlanırsa desteği ne olursa olsun kullanıcıyı manuel olarak yeniden yönlendirir ve ardından HSTS üstbilgisini, başka istemci isteklerinin mümkünse tarayıcı tarafından yeniden yönlendirilmesi için ayarlar.


Diğer başlıklar arasında bu başlığa yer vermediyse şaşırdım, bu oldukça önemli ... ikisini birleştirmenin bir sakıncası var mı?
keisar

Hayır ... HTTPS'yi her zaman istiyorsanız kesinlikle bu başlığı ayarlayabilirsiniz. Yönlendirmeyi yapmadan önce ve sonra ayarlamak bir nevi gereksizdir. Ayrıca uyumluluğu daha doğru bir şekilde açıklamak için yukarıdaki yanıtımı değiştirdim.
Jacob Swartwood

1
(Orijinal yorumu düzeltme) "Yalnızca bir sayfa" nın özel gereksinimini fark etmedim. HSTS tüm sayfalara uygulanacaktır; cevabım teknik olarak yanlış.
Jacob Swartwood

4
FYI, standart RFC 6797 bölüm 7.2 "HSTS Ana Bilgisayarı, güvenli olmayan aktarım üzerinden aktarılan HTTP yanıtlarına STS başlık alanını KULLANMAMALIDIR" diyor. bu yüzden istek normal http olduğunda göndermeye gerek yok, tarayıcı standardı takip ederse göz ardı edilmelidir.
Frank Forte

1
@mark bir MITM varsa ve web siteniz bu başlığa sahip değilse, içerdiği bir oturumun http'ye gitmesine izin verebilirsiniz ve insanlar ayrıntılarını girer ve muhtemelen fark etmezler ve bir yönlendirme yardımcı olmaz ( orta siteye https ile bağlanacak ve http olarak sunulacaktır). Bu üstbilgiyi kullanmak istemci tarafında HTTPS'yi zorlar. Bu özellikle son WPA2 WiFi güvenlik açığı nedeniyle önemlidir.
Rudiger

19

Sadece bir .htaccess dosyası oluşturdum ve ekledim:

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

Çok basit!


9
// 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);
}

8

Bir yük dengeleyici arkasında çalışırken böyle bir şey yapmak zorunda kaldı. Şapka ipucu 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;
    }
}

6

PHP yolu:

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

Apache mod_rewrite yolu:

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

SSL ihtiyacını geçersiz kılmak istediğim için PHP yolu tercih ederim. Örneğin, API'lara ve Mozilla Thunderbird'ün otomatik yapılandırması vb. Gibi yerel erişim
Jay

PHP yöntemi benim için mükemmel çalışıyor, şiddetle tavsiye edilir.
Moxet Ocak

5

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

Bazen kullanıcının sitenize güvenli bağlantı üzerinden göz attığından emin olmanız gerekebilir. Kullanıcıyı her zaman güvenli bağlantıya yönlendirmenin kolay bir yolu (https: //), aşağıdaki satırları içeren bir .htaccess dosyasıyla gerçekleştirilebilir:

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

Lütfen, .htaccess'in web sitesi ana klasöründe bulunması gerektiğini unutmayın.

Belirli bir klasör için HTTPS'yi zorlamak istiyorsanız şunları kullanabilirsiniz:

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

.Htaccess dosyası, HTTPS'yi zorlamanız gereken klasöre yerleştirilmelidir.


5

Tamam .. Şimdi bu konuda tonlarca şey var ama kimse "Güvenli" soruyu gerçekten tamamlamıyor. Benim için güvensiz bir şey kullanmak çok saçma.

Yem olarak kullanmadığınız sürece.

$ _SERVER yayılımı, nasıl olduğunu bilen birinin isteğiyle değiştirilebilir.

Ayrıca Sazzad Tushar Khan ve thebigjc'in de belirttiği gibi, bunu yapmak için httaccess'i de kullanabilirsiniz ve burada içeren birçok cevap var.

Sadece ekle:

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

.httaccess'inizde olanın sonuna kadar.

Yine de bu 2 araçla olabildiğince güvenli değiliz.

Gerisi basit. Eksik özellikler varsa yani ...

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

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


Ayrıca httaccess dosyanızı güncellediğinizi ve şunları kontrol ettiğinizi varsayalım:

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

Kontrol edebileceğiniz çok daha fazla değişken var.

HOST_URI (Kontrol edilecek statik öznitelikler varsa)

HTTP_USER_AGENT (Aynı oturumda farklı değerler)

Yani tüm söylediğim cevap bir kombinasyon halinde olduğunda sadece biri ya da diğeri için razı değil.

Daha httaccess bilgi yeniden yazma için docs-> bkz http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

Burada bazı Yığınları -> Kuvvet SSL / https .htaccess ve mod_rewrite kullanarak
ve
tam URL'sini alma geçerli sayfayı (PHP)
çift ​​olarak adlandırır.


2
ama şimdi aşağıdaki hatayı alıyorum: ERR_TOO_MANY_REDIRECTS. Bunu nasıl düzeltirim?
Pathros

3

SSL$_SERVER['HTTPS'] olup olmadığını söylemek için kullanın ve değilse doğru yere yönlendirin.

Unutmayın, formu görüntüleyen sayfanın HTTPS ile beslenmesi gerekmez, en çok ihtiyaç duyulan geri gönderme URL'sidir.

Düzenleme : evet, aşağıda belirtildiği gibi, tüm süreci HTTPS'ye sahip olmak en iyisidir. Çok daha güven verici - yazının en kritik kısım olduğuna işaret ediyordum. Ayrıca, çerezlerin güvenli olarak ayarlandığından emin olmanız gerekir, böylece yalnızca SSL ile gönderilirler. Mod_rewrite çözümü de çok şık, kendi web sitemde birçok uygulama güvenliğini sağlamak için kullandım.


Formun kendisinin https olması gerekmediği doğrudur, ancak bunu bilmeyen insanların çoğunluğu için iyi bir fikirdir. Formu göndermek üzereyken ve kilit simgesinin orada olmadığını fark ederse, yanlışlıkla formun güvensiz olduğunu varsayabilirler.
Graeme Perrow

1
@Graeme: ayrıca hiç kimse formun https yoluyla gönderileceğinden emin olamaz. Tüm form (http aracılığıyla görüntülenir), bilinmeyen veya http açık metin sitesine gönderilen sahte olabilir. Https sadece şifreleme ile ilgili değil, aynı zamanda sunucunun kimliğini de doğrular.
Olaf Kock

3

kullanın 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]

1

HTTP ve HTTPS'yi aynı sayfada karıştırmayın. HTTP aracılığıyla sunulan bir form sayfanız varsa, veri gönderme konusunda gergin olacağım - bir Görünüm Kaynağı yapmadan ve bunun için avlamadan gönderme HTTPS veya HTTP üzerinden gidip gitmediğini göremiyorum.

Formu HTTPS üzerinden gönderme bağlantısıyla birlikte sunmak, avantaj için büyük bir değişiklik değildir.


1

Apache veya .htaccess dosyalarını destekleyen LiteSpeed ​​gibi bir şey kullanıyorsanız, aşağıdakileri yapabilirsiniz. Zaten bir .htaccess dosyanız yoksa, kök dizininizde (genellikle index.php dosyanızın bulunduğu yerde) yeni bir .htaccess dosyası oluşturmanız gerekir. Şimdi bu satırları .htaccess'inizdeki ilk yeniden yazma kuralları olarak ekleyin:

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

Tüm yeniden yazma kuralları için .htaccess öğenizde yalnızca "RewriteEngine On" komutuna ihtiyacınız vardır, bu nedenle zaten varsa ikinci ve üçüncü satırı kopyalayın.

Umarım bu yardımcı olur.


Benim için işe yarayan ve Zend 2 benzeri bir çerçevede kendi senaryolarımda kullandığım şey bu - Downvote'u anlamıyorum.
Antonio

Cevap hemen hemen aynı olduğu için belki downvoted var bu bir daha bir yıl önce daha gönderilmiş @MatHatrik dan?
Wilt

1

Bunu kullanmak yeterli DEĞİLDİR:

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

Herhangi bir http içeriğiniz varsa (harici bir http resim kaynağı gibi), tarayıcı olası bir tehdidi algılar. Kodunuzdaki tüm ref ve src'lerinizin https olduğundan emin olun


1

Ben $ _SERVER [HTTPS] durumunu kontrol ile birçok çözüm olmuştur, ancak bazen komut dosyası dahili döngü yönlendirme neden neden ayarlanmış veya açık, kapalı, vb ayarlayın çünkü güvenilir değil gibi görünüyor.

Sunucunuz $ _SERVER [SCRIPT_URI] 'u destekliyorsa, en güvenilir çözüm

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;
}

Yüklemenize bağlı olarak, sunucunuzun $ _SERVER [SCRIPT_URI] 'u desteklemeyebileceğini, ancak destekliyorsa, kullanılacak daha iyi komut dosyası olduğunu lütfen unutmayın.

Buradan kontrol edebilirsiniz: Bazı PHP kurulumlarında neden $ _SERVER ['SCRIPT_URI'] var, bazılarında ise


1

IIS'yi bu satırı web.config dosyasına ekleyenler için yardımcı olacaktır:

<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>

Tam bir örnek dosya

<?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>

Soru özellikle IIS değil Apache'yi soruyor.
Quentin

1
A) etiketlenmemiş apache. Apache tırnak işaretleri arasında ölçülür. B) genel olarak apache ile ilgisi olmayan genel bir sorudur. Birden çok php destekleyen web sunucuları için geçerlidir
Tschallacka

0

Güvenlik nedeniyle olmamalısınız. Özellikle burada kurabiyeler varsa. Sizi çerez tabanlı tekrar saldırılarına açık bırakır.

Her iki durumda da, ayarlamak için Apache kontrol kurallarını kullanmalısınız.

Ardından, HTTPS'nin etkinleştirildiğini test edebilir ve gerektiğinde yeniden yönlendirebilirsiniz.

Ödeme sayfasına yalnızca FORM POST'u (alma yok) kullanarak yönlendirmelisiniz ve POST'suz sayfaya erişim diğer sayfalara yönlendirilmelidir. (Bu insanları sıcak atlayarak yakalar.)

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

Başlamak için iyi bir yer, daha fazla özür dilemediğiniz için özür dileriz. Ama gerçekten gereken SSL aracılığıyla her şeyi sokuyorum.

Aşırı koruyucu, ama en azından daha az endişen var.


0

belki bu yardımcı olabilir, sen, web sitem için böyle yaptım, bir cazibe gibi çalışır:

$protocol = $_SERVER["HTTP_CF_VISITOR"];

if (!strstr($protocol, 'https')){
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

0

Bunu yapmak için PHP kullanmak istiyorsanız o zaman bu şekilde benim için gerçekten iyi çalıştı:


<?php

if(!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != "on") {
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"], true, 301);
    //Prevent the rest of the script from executing.
    exit;
}
?>

$ _SERVER superglobal dizisindeki HTTPS değişkenini "on" değerine eşit olup olmadığını kontrol eder. Değişken açık değilse.


-1

Bu komut dosyasını kullandım ve site üzerinden iyi çalışıyor.

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();
}

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

Çok kolay.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.