PHP Uzyskaj protokół URL witryny - http vs https


197

Napisałem małą funkcję do ustanowienia bieżącego protokołu adresu URL witryny, ale nie mam protokołu SSL i nie wiem, jak sprawdzić, czy działa on pod https. Czy możesz mi powiedzieć, czy to prawda?

function siteURL()
{
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $domainName = $_SERVER['HTTP_HOST'].'/';
    return $protocol.$domainName;
}
define( 'SITE_URL', siteURL() );

Czy trzeba to zrobić jak wyżej, czy mogę to po prostu zrobić ?:

function siteURL()
{
    $protocol = 'http://';
    $domainName = $_SERVER['HTTP_HOST'].'/'
    return $protocol.$domainName;
}
define( 'SITE_URL', siteURL() );

W trybie SSL serwer nie konwertuje automatycznie adresu URL na https, nawet jeśli adres URL tagu kotwicy używa http? Czy konieczne jest sprawdzenie protokołu?

Dziękuję Ci!


1
Czy nie byłoby lepszym rozwiązaniem dla ciebie, aby zainstalować lokalny serwer WWW i rzucić na niego certyfikat SSL z podpisem własnym? W ten sposób możesz sam to przetestować.
Frazell Thomas

Tak, byłoby świetnie, ale nie wiem jak to zrobić.

4
Chociaż to nie odpowiada na twoje pytanie, lepszym rozwiązaniem twojego problemu (choć nie jestem pewien, nie wiedząc więcej) może być użycie względnych adresów URL protokołu .
Reese Moore,

Krótkie pytanie ... dlaczego wykonujesz funkcję, jeśli nie jest dynamiczna. To nie jest tak, że karmisz go dowolnymi zmiennymi, aby zmienić adres URL. Dlaczego nie zdefiniować stałej? To jest to co zrobiłem. $ Protocol = (! empty ($ _ SERVER ['HTTPS']) && $ _SERVER ['HTTPS']! == 'off' || $ _SERVER ['SERVER_PORT'] == 443)? „https: //”: „http: //”; zdefiniuj ('SITE_URL', $ protokół. $ _ SERVER ['HTTP_HOST']. '/');
HTMLGuy

Odpowiedzi:


69

To nie jest automatyczne. Twoja najlepsza funkcja wygląda dobrze.


19
warto zauważyć, że jest on automatyczny, jeśli po prostu zrezygnujesz z protokołu ... tj. //mysqite.comzamiasthttps://mysitecom
raz walczyłem z niedźwiedziem.

4
@Pamblam, // działa świetnie, chyba że twój link znajduje się w e-mailu :)
TimoSolo

Lub na życzenie xhr
Lucas Morgan

86

Wiem, że jest późno, chociaż istnieje znacznie wygodniejszy sposób rozwiązania tego rodzaju problemu! Inne rozwiązania są dość nieuporządkowane; tak bym to zrobił:

$protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === 0 ? 'https://' : 'http://';

... lub nawet bez warunku, jeśli wolisz:

$protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,strpos( $_SERVER["SERVER_PROTOCOL"],'/'))).'://';

Spójrz na $_SERVER["SERVER_PROTOCOL"]


20
To nie działa z „https” stackoverflow.com/questions/16825243/…
wormhit

@ Wormhit zależy to jednak głównie od konfiguracji serwera
Ivo

Masz powód, dla którego używasz striposzamiast strpos?
Fred

12
$_SERVER['SERVER_PROTOCOL']jest przeznaczony do przechowywania HTTP/1.0lub, w HTTP/1.1zależności od wersji protokołu, o jakiej konfiguracji serwera HTTP mówisz, przechowując httpsinformacje o tym ciągu pochodzącym z zapytania http?
regilero

1
W moim przypadku nie działa! $ _SERVER ['SERVER_PROTOCOL'] zawiera „HTTP” (bez „S”), podczas gdy protokół to https. Sprawdzanie $ _SERVER ['HTTPS'] jest bardziej odpowiednie.
Simon Hi

68

To działa dla mnie

if (isset($_SERVER['HTTPS']) &&
    ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
    isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
    $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $protocol = 'https://';
}
else {
  $protocol = 'http://';
}

3
Jest to rozwiązanie, które działa, jeśli używasz proxy (jak w moim przypadku CloudFlare)
Jesús Carrera

1
To prawda - nie powinieneś zakładać https tylko dlatego, że używasz portu 443.
Mark Fisher

24

Trochę zmian:

function siteURL() {
  $protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || 
    $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
  $domainName = $_SERVER['HTTP_HOST'];
  return $protocol.$domainName;
}

16

krótka droga

$scheme = $_SERVER['REQUEST_SCHEME'] . '://';

3
REQUEST_SCHEMEnie jest wiarygodny
Farnabaz

5
REQUEST_SCHEME jest niedostępny do Apache 2.4.
KenB

7

Ponieważ testowanie numeru portu nie jest według mnie dobrą praktyką, moim rozwiązaniem jest:

define('HTTPS', isset($_SERVER['HTTPS']) && filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN));

Te HTTPSciągłe powroty TRUEjeśli $_SERVER['HTTPS']jest ustawiony i jest równy „1”, „prawda”, „on” lub „tak”. W przeciwnym razie zwraca FALSE.


To prawdopodobnie najlepsza odpowiedź. Wiele z tych odpowiedzi będzie tylko w niektórych sytuacjach. Na przykład ludzie sprawdzają tylko, czy ustawiono $ _SERVER ['HTTPS']. Wiele frameworków ustawia tę zmienną na false lub „off” itd., Dlatego sprawdzanie, czy jest ona po prostu ustawiona, nie będzie działać.
Daniel Dewhurst

1
Chociaż działa to w większości sytuacji, zdarzały się sytuacje, w których istniała konfiguracja SNAFU, a $ _SERVER ['HTTPS'] faktycznie był ustawiony na „off”. Twój kod nadal uważa to za „zaliczenie” testu, dlatego należy je zmienić, aby uwzględnić to konkretne ustawienie.
Dave Morton

6

W przypadku dowolnego systemu z wyjątkiem IIS wystarczy to do zdefiniowania własnego adresu URL witryny:

$siteURL='http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['HTTP_HOST'].'/';

lub

$siteURL='http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['SERVER_NAME'].'/';

zależy od tego, czego dokładnie chcesz: HTTP_HOST vs. SERVER_NAME


5

W przypadku proxy SERVER_PORTmoże nie podać poprawnej wartości, więc to działało dla mnie -

$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 || $_SERVER['HTTP_X_FORWARDED_PORT'] == 443) ? "https://" : "http://"

4

Użyj tej zmiennej serwera, aby uzyskać szczegółowe informacje o protokole:

 $scheme = $_SERVER['REQUEST_SCHEME'] . '://';
 echo $scheme; //it gives http:// or https://

Zauważ, że ta zmienna serwera jest zawodna. Aby uzyskać więcej informacji, spójrz na: Czy $ _SERVER ['REQUEST_SCHEME'] jest solidny?


Czy możesz dodać więcej informacji do swojego posta, a nie tylko kod? Na przykład wyjaśnij, dlaczego jest to odpowiedź na pytanie?
ndsmyter,

3

Wiem, że to stare pytanie, ale dzisiaj się z tym spotkałem, ponieważ musiałem je przetestować na mojej stronie. Wydaje się, że powyższe odpowiedzi są niepotrzebnie skomplikowane. Aby ustalić protokół witryny, wystarczy przetestować$_SERVER['HTTPS']

Jeśli protokół używa HTTPS, wówczas $_SERVER['HTTPS']zwróci „on”. Jeśli nie, zmienna pozostanie pusta. Na przykład:
// test if HTTPS is being used. If it is, the echo will return '$SSL_test: on'. If not HTTPS, '$SSL_test' will remain empty.

$SSL_test = $_SERVER['HTTPS'];

echo '<p>$SSL_test: '.$SSL_test.'</p>';

if($SSL_test == true) {
    echo 'You\'re using SSL';
} else {
    echo 'You\'re not using SSL';
} 

Możesz użyć powyższego, aby łatwo i czysto przetestować HTTPS i odpowiednio zaimplementować. :)


2
Nie każdy serwer ma ten $ _SERVER ['HTTPS']
ChrisDeDavidMindflowAU

2

wykonał funkcję przy użyciu odpowiedzi Rid Iculous , która działała w moim systemie.

function site_protocol() {
    if(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&  $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')  return $protocol = 'https://'; else return $protocol = 'http://';
}

Mam nadzieję, że to pomoże


2

Przetestowałem najczęściej głosowaną odpowiedź i nie działało to dla mnie , w końcu użyłem:

$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';

Niektóre serwery sieciowe nie obsługują, $_SERVER["HTTPS"]dlatego kod może zwrócić, http://nawet jeśli powinienhttps://
nathanfranke

Jeśli serwer nie obsługuje https, dlaczego kod nadal miałby zwracać https?
CONvid19

Mój serwer obsługuje https, ale $_SERVER["HTTPS"]zmienna nigdy nie jest zdefiniowana.
nathanfranke

Jestem zdezorientowany twoimi 2 komentarzami. Prawdopodobnie lepiej, jeśli utworzysz nową odpowiedź obejmującą te szczególne przypadki. Dzięki i powodzenia!
CONvid19

2
$protocal = 'http';
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || $_SERVER['HTTPS'] == 'on') {$protocal = 'https';}


echo $protocal;

2

Wyodrębniono z CodeIgniter:

if ( ! function_exists('is_https'))
{
    /**
     * Is HTTPS?
     *
     * Determines if the application is accessed via an encrypted
     * (HTTPS) connection.
     *
     * @return  bool
     */
    function is_https()
    {
        if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
        {
            return TRUE;
        }
        elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
        {
            return TRUE;
        }
        elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
        {
            return TRUE;
        }

        return FALSE;
    }
}

0

to najlepsze rozwiązanie https lub http użyj tego:

<?php
$protocol = '//';  
$site_url = $protocol.$_SERVER["HTTP_HOST"];
?>

Ale nie może wyświetlać https ani http, więc służy tylko do łączenia treści witryny, takich jak obraz itp.

jeśli chcesz przekierować swoją stronę w https, dodaj ten kod do pliku .htaccess:

<IfModule mod_rewrite.c>
 RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
 RewriteRule ^(.*)$ https://www.your-domain.com$1 [L]
</IfModule>

Zmień adres www.twoja-domena.com na swoją nazwę dowmain.


0

Oto jak to zrobić ... to jest skróconą if else wersją RID Iculous za odpowiedź ...

$protocol = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] === 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ? 'https' : 'http';

0

Myślę, że cała funkcja powinna wyglądać następująco:

function siteURL()
{
    $protocol =  "http://";
    if (
        //straight
        isset($_SERVER['HTTPS']) && in_array($_SERVER['HTTPS'], ['on', 1])
        ||
        //proxy forwarding
        isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'
    ) {
        $protocol = 'https://';
    }

    $domainName = $_SERVER['HTTP_HOST'];
    return $protocol . $domainName;
}

Uwagi:

  • powinieneś także poszukać HTTP_X_FORWARDED_PROTO (np. jeśli serwer proxy)
  • poleganie na porcie 443 nie jest bezpieczne (https może być obsługiwany na innym porcie)
  • REQUEST_SCHEME nie jest wiarygodny

0

Wiem, że jestem trochę spóźniony na tę imprezę, ale jeśli wolisz nie używać $ _SERVER, ponieważ jest to zdecydowanie odradzane, a nawet dezaktywowane w niektórych frameworkach PHP; i masz serwer WWW Apache, możesz w ten sposób użyć jego natywnego polecenia: -

$protocol = apache_getenv('HTTPS') ? 'https:' : 'http:';
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.