จะทราบได้อย่างไรว่าคุณใช้ HTTPS โดยไม่มี $ _SERVER ['HTTPS']


190

ฉันเห็นบทเรียนออนไลน์มากมายที่บอกว่าคุณต้องตรวจสอบ$_SERVER['HTTPS']ว่าเซิร์ฟเวอร์มีการเชื่อมต่อที่ปลอดภัยด้วย HTTPS หรือไม่ ปัญหาของฉันคือเซิร์ฟเวอร์บางตัวที่ฉันใช้$_SERVER['HTTPS']เป็นตัวแปรที่ไม่ได้กำหนดซึ่งส่งผลให้เกิดข้อผิดพลาด มีตัวแปรอื่นที่ฉันสามารถตรวจสอบได้ว่าควรกำหนดไว้หรือไม่?

เพื่อความชัดเจนฉันกำลังใช้รหัสนี้เพื่อแก้ไขหากเป็นการเชื่อมต่อ HTTPS:

if(isset($_SERVER['HTTPS'])) {
    if ($_SERVER['HTTPS'] == "on") {
        $secure_connection = true;
    }
}

ไม่ว่าในกรณีใดก็ตามเซิร์ฟเวอร์ที่ $ _SERVER ['HTTPS'] ไม่ได้กำหนดกำลังทำงานบน HTTPS
Freddy

ที่จริงแล้วหนึ่งในนั้นคือเซิร์ฟเวอร์ WAMP ที่บ้านของฉัน และฉันไม่เชื่อว่ามันทำงานบน HTTPS
Tyler Carter

@TylerCarter วิธีอื่นคือการใช้Secureคุกกี้ ระวังด้วย gotchas แม้ว่า
Pacerier

คำตอบ:


280

สิ่งนี้ควรทำงานแม้ว่า $_SERVER['HTTPS']จะไม่ได้กำหนดไว้:

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

รหัสเข้ากันได้กับ IIS

จากเอกสาร PHP.net และความคิดเห็นของผู้ใช้ :

1) ตั้งเป็นค่าที่ไม่ว่างเปล่าหากสคริปต์ถูกสอบถามผ่านโปรโตคอล HTTPS

2) โปรดทราบว่าเมื่อใช้ ISAPI กับ IIS ค่าจะเป็น "ปิด" หากไม่ได้ทำการร้องขอผ่านโปรโตคอล HTTPS (มีการรายงานพฤติกรรมเดียวกันสำหรับ IIS7 ที่ใช้งาน PHP เป็นแอปพลิเคชัน Fast-CGI)

นอกจากนี้เซิร์ฟเวอร์ Apache 1.x (และการติดตั้งที่ใช้งานไม่ได้) อาจไม่ได้$_SERVER['HTTPS']กำหนดไว้แม้ว่าจะเชื่อมต่ออย่างปลอดภัย แม้ว่าจะไม่ได้รับประกันการเชื่อมต่อพอร์ต 443 มีโดยการประชุมมีแนวโน้มที่ใช้ซ็อกเก็ตที่เชื่อถือได้ดังนั้นการตรวจสอบพอร์ตเพิ่มเติม

หมายเหตุเพิ่มเติม: หากมี load balancer ระหว่างไคลเอ็นต์และเซิร์ฟเวอร์ของคุณรหัสนี้จะไม่ทดสอบการเชื่อมต่อระหว่างไคลเอ็นต์และ load balancer แต่เป็นการเชื่อมต่อระหว่าง load balancer และเซิร์ฟเวอร์ของคุณ หากต้องการทดสอบการเชื่อมต่อเดิมคุณจะต้องทดสอบโดยใช้HTTP_X_FORWARDED_PROTOส่วนหัว แต่จะซับซ้อนกว่า ดูความคิดเห็นล่าสุดด้านล่างคำตอบนี้


50
Nb: พอร์ต 443 ไม่รับประกันว่าจะมีการเข้ารหัสการเชื่อมต่อ
ErichBSchulz

2
@DavidRodrigues นั่นไม่จริง คุณสามารถใช้ HTTP / HTTPS ผ่านพอร์ตใดก็ได้ที่คุณต้องการ getservbyname()เป็นเพียงการอ้างอิงไม่ใช่ความจริงและไม่รับประกันว่า HTTPS จะทำงานผ่านพอร์ต 443 แต่อย่างใด
Brad

1
ฉันมีปัญหาเล็กน้อยกับ$_SERVER['SERVER_PORT'] !== 443ฉันต้องโยน$_SERVER['SERVER_PORT]ให้เป็นจำนวนเต็มดังนี้:intval($_SERVER['SERVER_PORT]) !== 443
meconroy

1
1) การตรวจสอบพอร์ตของเซิร์ฟเวอร์เป็นสิ่งที่พิเศษสำหรับเซิร์ฟเวอร์ sheetty ที่ดีที่สุดที่จะลบออกหากไม่จำเป็น 2) สังเกตว่าเป็นการเปรียบเทียบที่หลวมในคำตอบของฉัน;)
Gras Double

1
อีกหนึ่งเรื่องเล็ก ๆ ที่ฉันเจอในวันนี้ เซิร์ฟเวอร์ส่งคืน 'ปิด' ไม่ใช่ 'ปิด' - strtolower($_SERVER['HTTPS']) !== 'off'ทำเคล็ดลับ
jhummel

117

โซลูชันของฉัน (เนื่องจากเงื่อนไขมาตรฐาน [$ _SERVER ['HTTPS'] == 'เปิด'] ไม่ทำงานบนเซิร์ฟเวอร์ที่อยู่เบื้องหลังตัวโหลดบาลานซ์):

$isSecure = false;
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
    $isSecure = true;
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
    $isSecure = true;
}
$REQUEST_PROTOCOL = $isSecure ? 'https' : 'http';

HTTP_X_FORWARDED_PROTO: มาตรฐานตามความเป็นจริงสำหรับการระบุโปรโตคอลเริ่มต้นของคำขอ HTTP เนื่องจาก reverse proxy (load balancer) อาจสื่อสารกับเว็บเซิร์ฟเวอร์โดยใช้ HTTP แม้ว่าคำขอไปยัง reverse proxy คือ HTTPS http: //en.wikipedia org / วิกิพีเดีย / List_of_HTTP_header_fields # Common_non-standard_request_headers


4
นี่เป็นวิธีแก้ปัญหาถ้าคุณใช้ reverse proxy วานิช
Reto Zahner

1
ปัญหาของฉันได้รับการแก้ไขด้วยวิธีนี้ (PHP - AWS Elastic
beanstalk

นี่เป็นวิธีแก้ปัญหาหากคุณใช้ตัวโหลดบาลานซ์
Abhishek Saini

คุณเป็นไฟล์ประเภทใด? ฉันสมมติว่านี่ไม่ได้อยู่ในไฟล์. htaccess
Jordan

5
นอกจากนี้ยังใช้งานได้กับ HTTPS ฟรีที่ CloudFlare ให้บริการฟรี
AnthonyVO

82

Chacha ตามเอกสาร PHP: "ตั้งค่าที่ไม่ว่างเปล่าหากสคริปต์ถูกสอบถามผ่านโปรโตคอล HTTPS" ดังนั้นหากข้อความสั่งของคุณจะส่งคืนเท็จในหลายกรณีที่เปิดใช้ HTTPS คุณจะต้องยืนยันว่า$_SERVER['HTTPS']มีอยู่และไม่ว่างเปล่า ในกรณีที่ HTTPS ไม่ได้ตั้งค่าอย่างถูกต้องสำหรับเซิร์ฟเวอร์ที่กำหนดคุณสามารถลองตรวจสอบว่า$_SERVER['SERVER_PORT'] == 443ไม่ได้ตั้งค่าอย่างถูกต้องสำหรับเซิร์ฟเวอร์ที่กำหนดคุณสามารถลองตรวจสอบว่า

แต่โปรดทราบว่าบางเซิร์ฟเวอร์จะตั้งค่าด้วย $_SERVER['HTTPS']ที่ไม่ว่างด้วยดังนั้นโปรดตรวจสอบตัวแปรนี้ด้วย

อ้างอิง: เอกสารสำหรับ$_SERVERและ$HTTP_SERVER_VARS[คัดค้าน]


12
ใช้ $ _SERVER ['SERVER_PORT'] อาจยุ่งยาก ... ตัวอย่างเช่น ispconfig ใช้พอร์ต 81 เป็นพอร์ตที่ปลอดภัยดังนั้นให้บอกว่า 443 เป็นพอร์ต "default" สำหรับ ssl
Gabriel Sosa

@Gabriel Sosa - จริง แต่คำเตือนสามารถแก้ไขได้เป็นกรณี ๆ ไป คำตอบของ @ hobodave จะได้ผลมากที่สุด
Tim Post

โปรดทราบว่าสิ่งนี้จะไม่ทำงานหลังพร็อกซีย้อนกลับ หนึ่งอาจพิจารณาที่จะตรวจสอบHTTP_X_FORWARDED_PROTOหรือHTTP_X_FORWARDED_SSLเช่นกัน
เปาโล

1
ฉันเห็นด้วยกับที่พึ่งสุดท้ายควรเป็นหมายเลขพอร์ตดังนั้นนี่คือเช็คของฉัน: (((isset($_SERVER['HTTPS'])) && (strtolower($_SERVER['HTTPS']) == 'on')) || ((isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) && (strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https'))) ซึ่งไม่รวมถึงการตรวจสอบพอร์ตเลย รู้สึกอิสระที่จะเพิ่ม :-)
Roland

@ เปาโลที่อยู่เบื้องหลังพร็อกซีย้อนกลับSetEnvIf X-Forwarded-SSL on HTTPS=onจะทำเคล็ดลับ แต่สิ่งนี้จะไม่ทำงานด้วยREQUEST_SCHEMEเหตุที่ทำให้ PHP ดูเหมือนว่าจะใช้งานได้ดีกว่า$_SERVER['HTTPS']
แอนโทนีกิ๊บส์

14

สิ่งนี้จะทำงานเมื่อ$_SERVER['HTTPS']ไม่ได้กำหนด

if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 ){
    //enable secure connection
}

2
เป็นเซิร์ฟเวอร์บางตัวที่$_SERVER['HTTPS']ไม่ได้กำหนด แต่เปิดใช้งาน https แล้วมันล่ะ?
John Max

1
@JohnMax SERVER_PORTถูกกำหนดไว้เสมอว่าจะแก้ปัญหาที่ไม่ได้กำหนดHTTPS
Thamaraiselvam

11

ฉันเพิ่งมีปัญหาที่ฉันใช้เซิร์ฟเวอร์โดยใช้ Apache mod_ssl แต่ phpinfo () และ var_dump ($ _SERVER) แสดงให้เห็นว่า PHP ยังคงคิดว่าฉันใช้พอร์ต 80

นี่คือวิธีแก้ปัญหาของฉันสำหรับทุกคนที่มีปัญหาเดียวกัน ....

<VirtualHost *:443>
  SetEnv HTTPS on
  DocumentRoot /var/www/vhost/scratch/content
  ServerName scratch.example.com
</VirtualHost>

บรรทัดที่ควรสังเกตคือบรรทัด SetEnv ด้วยสิ่งนี้ในและหลังการรีสตาร์ทคุณควรมีตัวแปรสภาพแวดล้อม HTTPS ที่คุณใฝ่ฝัน


5
ดีกว่าต้องแน่ใจว่า HTTPS ทำงานได้อย่างแท้จริง นั่นจะทำให้เซิร์ฟเวอร์โกหกคุณถ้าไม่ใช่
แบรดโคช์ส

นอกจากนี้คุณต้องใช้โมดูล SetEnv เพื่อให้สามารถใช้งานได้ มันเปิดใช้งานโดยค่าเริ่มต้น แต่คุณไม่เคยรู้ว่าผู้ดูแลเซิร์ฟเวอร์อาจปิดการใช้งาน
toon81

มีประโยชน์มากในกรณีที่คุณอยู่บน docker ถึง reverse proxy ขอบคุณ!
dikirill

8

ทำให้ฟังก์ชั่นของฉันเองไม่ให้อ่านโพสต์ก่อนหน้าทั้งหมด:

public static function isHttps()
{
    if (array_key_exists("HTTPS", $_SERVER) && 'on' === $_SERVER["HTTPS"]) {
        return true;
    }
    if (array_key_exists("SERVER_PORT", $_SERVER) && 443 === (int)$_SERVER["SERVER_PORT"]) {
        return true;
    }
    if (array_key_exists("HTTP_X_FORWARDED_SSL", $_SERVER) && 'on' === $_SERVER["HTTP_X_FORWARDED_SSL"]) {
        return true;
    }
    if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER) && 'https' === $_SERVER["HTTP_X_FORWARDED_PROTO"]) {
        return true;
    }
    return false;
}

7

หากคุณใช้ Apache คุณอาจไว้ใจได้ตลอดเวลา

$_SERVER["REQUEST_SCHEME"]

เพื่อตรวจสอบรูปแบบของ URL ที่ร้องขอ แต่ดังที่กล่าวไว้ในคำตอบอื่น ๆ มันเป็นความรอบคอบในการตรวจสอบพารามิเตอร์อื่น ๆ ก่อนที่จะสมมติว่า SSL กำลังถูกใช้งานจริง


มันใช้งานได้กับ XAMPP แต่ไม่ใช่ใน centos / apache2 + PHP ... ดังนั้นจึงไม่น่าเชื่อถือ
Firas Abd Alrahman

5

คำตอบที่แท้จริง: พร้อมสำหรับการคัดลอกวางลงในสคริปต์ [config]

/* configuration settings; X=edit may 10th '11 */
$pv_sslport=443; /* for it might be different, as also Gabriel Sosa stated */
$pv_serverport=80; /* X */
$pv_servername="mysite.com"; /* X */

/* X appended after correction by Michael Kopinsky */
if(!isset($_SERVER["SERVER_NAME"]) || !$_SERVER["SERVER_NAME"]) {
    if(!isset($_ENV["SERVER_NAME"])) {
        getenv("SERVER_NAME");
        // Set to env server_name
        $_SERVER["SERVER_NAME"]=$_ENV["SERVER_NAME"];
    }
}
if(!$_SERVER["SERVER_NAME"]) (
    /* X server name still empty? ... you might set $_SERVER["SERVER_NAME"]=$pv_servername; */
}

if(!isset($_SERVER["SERVER_PORT"]) || !$_SERVER["SERVER_PORT"]) {
    if(!isset($_ENV["SERVER_PORT"])) {
        getenv("SERVER_PORT");
        $_SERVER["SERVER_PORT"]=$_ENV["SERVER_PORT"];
    }
}
if(!$_SERVER["SERVER_PORT"]) (
    /* X server port still empty? ... you might set $_SERVER["SERVER_PORT"]=$pv_serverport; */
}

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

$pv_URIprotocolถูกต้องแล้วและพร้อมใช้งาน $site=$pv_URIprotocol.$_SERVER["SERVER_NAME"]ตัวอย่าง โดยธรรมชาติแล้วสตริงสามารถถูกแทนที่ด้วย TRUE และ FALSE ได้เช่นกัน PV ย่อมาจาก PortalPress Variable เนื่องจากเป็น copy-paste โดยตรงซึ่งจะทำงานตลอดเวลา ชิ้นนี้สามารถใช้ในสคริปต์การผลิต


3

ฉันไม่คิดว่าการเพิ่มพอร์ตเป็นความคิดที่ดีโดยเฉพาะเมื่อคุณมีเซิร์ฟเวอร์จำนวนมากที่มีบิลด์ต่างกัน ที่เพิ่งเพิ่มอีกสิ่งหนึ่งที่ต้องจำไว้เพื่อเปลี่ยนแปลง ดู doc ของฉันคิดว่าบรรทัดสุดท้ายของ kaisers ค่อนข้างดีดังนั้น:

if(!empty($_SERVER["HTTPS"]))
  if($_SERVER["HTTPS"]!=="off")
    return 1; //https
  else
    return 0; //http
else
  return 0; //http

ดูเหมือนดีพอ


3

วิธีการที่เชื่อถือได้เพียงวิธีเดียวคือ Igor M.

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

พิจารณาสิ่งต่อไปนี้: คุณใช้ nginx กับ fastcgi โดยค่าเริ่มต้น (debian, ubuntu) fastgi_params มีคำสั่ง:

fastcgi_param HTTPS $ https;

หากคุณไม่ได้ใช้ SSL จะได้รับการแปลเป็นค่าว่างไม่ใช่ 'ปิด' ไม่ใช่ 0 และคุณถึงวาระแล้ว

http://unpec.blogspot.cz/2013/01/nette-nginx-php-fpm-redirect.html


3

ฉันพบว่าพารามิเตอร์เหล่านี้ยอมรับได้และเป็นไปได้มากกว่าว่าจะไม่มีผลบวกปลอมเมื่อเปลี่ยนเว็บเซิร์ฟเวอร์

  1. $ _SERVER [ 'HTTPS_KEYSIZE']
  2. $ _SERVER [ 'HTTPS_SECRETKEYSIZE']
  3. $ _SERVER [ 'HTTPS_SERVER_ISSUER']
  4. $ _SERVER [ 'HTTPS_SERVER_SUBJECT']

    if($_SERVER['HTTPS_KEYSIZE'] != NULL){/*do foobar*/}

สิ่งนี้ไม่ได้บอกอะไรคุณเกี่ยวกับการใช้ HTTPS ด้วยโหลดบาลานซ์ / พร็อกซี
แบรด

3

วิธีที่สั้นที่สุดที่ฉันใช้:

$secure_connection = !empty($_SERVER['HTTPS']);

ถ้าหากใช้ https แล้ว $ secure_connection เป็นจริง


echo (!empty($_SERVER['HTTPS'])?'https':'http');ให้คุณhttpหรือhttps
Xavi Esteve

ทำมัน(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
Tivie

2

คุณสามารถตรวจสอบได้$_SERVER['SERVER_PORT']ว่า SSL ทำงานบนพอร์ต 443 แต่ไม่สามารถป้องกันได้


อย่างไรก็ตาม $ _SERVER ['SERVER_PORT']
Tyler Carter

2

คุณคิดยังไงกับสิ่งนี้?

if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
    $scheme = 'https';
else
    $scheme = 'http';

ใช่แล้ว หากคุณพึ่งพาที่ว่างเปล่าเท่านั้น () PHP จะออกโดยมีข้อผิดพลาดหากไม่มีดัชนี 'HTTPS'
toni rmc

3
"empty () มีความสำคัญเทียบเท่ากับ! isset ($ var) || $ var == false" - php.net/manual/en/function.empty.php
John Magnolia

2
คุณพูดถูก ตลกฉันคิดถึงสิ่งนั้น ฉันมักจะคิดว่า empty () จะล้มเหลวหากไม่มีตัวแปร
toni rmc

2

บนเซิร์ฟเวอร์ของฉัน (Ubuntu 14.10, Apache 2.4, php 5.5) $_SERVER['HTTPS']ไม่ได้ตั้งค่าไว้เมื่อโหลดสคริปต์ php ผ่าน https ฉันไม่รู้ว่าผิดอะไร แต่บรรทัดต่อไปนี้ใน.htaccessไฟล์แก้ไขปัญหานี้:

RewriteEngine on

RewriteCond %{HTTPS} =on [NC] 
RewriteRule .* - [E=HTTPS:on,NE]

1

นี่คือฟังก์ชั่นที่ใช้งานซ้ำได้ที่ฉันใช้มาระยะหนึ่งแล้ว HTH

หมายเหตุ: ค่าของ HTTPS_PORT (ซึ่งเป็นค่าคงที่ที่กำหนดเองในรหัสของฉัน) อาจแตกต่างกันไปตาม envrionment ของคุณตัวอย่างเช่นอาจเป็น 443 หรือ 81

/**
 * Determine if this is a secure HTTPS connection
 * 
 * @return  bool    True if it is a secure HTTPS connection, otherwise false.
 */
function isSSL()
{
    if (isset($_SERVER['HTTPS'])) {
        if ($_SERVER['HTTPS'] == 1) {
            return true;
        } elseif ($_SERVER['HTTPS'] == 'on') {
            return true;
        }
    } elseif ($_SERVER['SERVER_PORT'] == HTTPS_PORT) {
        return true;
    }

    return false;
}

1

เพียงเพื่อความสนใจนกขมิ้นโครเมี่ยมในขณะนี้ส่ง

HTTPS : 1

ไปยังเซิร์ฟเวอร์และขึ้นอยู่กับวิธีการกำหนดค่าเซิร์ฟเวอร์อาจหมายความว่าคุณได้รับต่อไปนี้

HTTPS : 1, on

สิ่งนี้ทำลายแอปพลิเคชันของเราเพราะเรากำลังทดสอบว่าเปิดหรือไม่ซึ่งเห็นได้ชัดว่าไม่ใช่ ในขณะนี้เฉพาะนกขมิ้นโครเมี่ยมที่ดูเหมือนว่าจะทำเช่นนี้ แต่มันก็คุ้มค่าที่จะสังเกตว่าสิ่งต่าง ๆ จากนกขมิ้นโดยทั่วไปในดินแดนโครเมียม "ปกติ" ในไม่ช้า


1

ถ้าคุณใช้ nginx เป็นระบบปรับสมดุลการโหลดให้ตรวจสอบ $ _SERVER ['HTTP_HTTPS'] == 1 การตรวจสอบอื่น ๆ จะล้มเหลวสำหรับ ssl


1
$secure_connection = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || (!empty($_SERVER['HTTP_HTTPS']) && $_SERVER['HTTP_HTTPS'] != 'off') || $_SERVER['REQUEST_SCHEME'] == 'https' || $_SERVER['SERVER_PORT'] == 443) ? true : false;

รหัสกำลังตรวจสอบทุกอย่างที่เป็นไปได้และทำงานบน IIS เว็บเซิร์ฟเวอร์ด้วย Chrome ตั้งแต่ v44 ไม่ได้ตั้งค่าส่วนหัว HTTP: 1 ดังนั้นการตรวจสอบ HTTP_HTTPS ก็โอเค หากรหัสนี้ไม่ตรงกับ https หมายความว่าเว็บเซิร์ฟเวอร์หรือพร็อกซีเซิร์ฟเวอร์ของคุณมีการกำหนดค่าไม่ดี Apache เองตั้งค่าสถานะ HTTPS อย่างถูกต้อง แต่อาจมีปัญหาเมื่อคุณใช้พรอกซี (เช่น nginx) คุณต้องตั้งค่าส่วนหัวในโฮสต์เสมือน nginx https

proxy_set_header   X-HTTPS 1;

และใช้โมดูล Apache บางตัวเพื่อตั้งค่าสถานะ HTTPS อย่างถูกต้องโดยค้นหา X-HTTPS จากพร็อกซี ค้นหา mod_fakessl, mod_rpaf ฯลฯ


0

หากคุณกำลังใช้ load balancer ของ Incapsula คุณจะต้องใช้ IRule เพื่อสร้างส่วนหัวที่กำหนดเองสำหรับเซิร์ฟเวอร์ของคุณ ฉันสร้างส่วนหัว HTTP_X_FORWARDED_PROTO ที่เท่ากับ "http" ถ้าพอร์ตถูกตั้งค่าเป็น 80 และ "https" หากเท่ากับ 443


0

ฉันจะเพิ่มตัวกรองทั่วโลกเพื่อให้แน่ใจว่าทุกสิ่งที่ฉันกำลังตรวจสอบนั้นถูกต้อง

function isSSL() {

    $https = filter_input(INPUT_SERVER, 'HTTPS');
    $port = filter_input(INPUT_SERVER, 'SERVER_PORT');
    if ($https) {

        if ($https == 1) {
            return true;
        } elseif ($https == 'on') {
            return true;
        }
    } elseif ($port == '443') {
        return true;
    }

    return false;
}

0

ฉันมีโอกาสที่จะก้าวไปอีกขั้นและตรวจสอบว่าไซต์ที่ฉันกำลังเชื่อมต่อนั้นสามารถใช้งาน SSL ได้หรือไม่ (หนึ่งโครงการถามผู้ใช้ถึง URL ของพวกเขาและเราต้องตรวจสอบว่าพวกเขาติดตั้ง API pack ของเราบนเว็บไซต์ http หรือ https)

นี่คือฟังก์ชั่นที่ฉันใช้ - โดยทั่วไปเพียงเรียก URL ผ่าน cURL เพื่อดูว่า https ใช้งานได้จริงหรือไม่!

function hasSSL($url) 
{
    // take the URL down to the domain name
    $domain = parse_url($url, PHP_URL_HOST);
    $ch = curl_init('https://' . $domain);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); //its a  HEAD
    curl_setopt($ch, CURLOPT_NOBODY, true);          // no body
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // in case of redirects
    curl_setopt($ch, CURLOPT_VERBOSE, 0); //turn on if debugging
    curl_setopt($ch, CURLOPT_HEADER, 1);     //head only wanted
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);    // we dont want to wait forever
    curl_exec($ch);
    $header = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($header === 200) {
        return true;
    }
    return false;
}

นี่เป็นวิธีที่น่าเชื่อถือที่สุดที่ฉันพบว่าไม่เพียง แต่ค้นหาว่าคุณใช้ https (ตามคำถามที่ถาม) แต่หากคุณสามารถใช้ (หรือแม้แต่ควรใช้) https ได้

หมายเหตุ: เป็นไปได้ (แม้ว่าจะไม่จริง ... ) ว่าไซต์อาจมีหน้า http และ https ที่แตกต่างกัน (ดังนั้นหากคุณได้รับคำแนะนำให้ใช้ http คุณอาจไม่จำเป็นต้องเปลี่ยน .. ) ไซต์ส่วนใหญ่ เหมือนกันและอาจเปลี่ยนเส้นทางตัวคุณเอง แต่การตรวจสอบเพิ่มเติมนี้มีการใช้งาน (แน่นอนอย่างที่ฉันพูดไว้ในโครงการที่ผู้ใช้ป้อนข้อมูลไซต์ของพวกเขาและคุณต้องการให้แน่ใจจากฝั่งเซิร์ฟเวอร์)


0

นี่คือวิธีที่ฉันจะแก้ปัญหานี้

$https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 ||
        !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
            strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0;

return ($https) ? 'https://' : 'http://';

0

ฉันใช้คำแนะนำหลักที่นี่และรำคาญที่ "ประกาศ PHP" ในบันทึกเมื่อไม่ได้ตั้งค่า HTTPS คุณสามารถหลีกเลี่ยงได้โดยใช้ตัวดำเนินการnull-coalescing "??":

if( ($_SERVER['HTTPS'] ?? 'off') == 'off' ) {
    // redirect
}

(หมายเหตุ: ไม่สามารถใช้ได้ก่อน php v7)


-7

ตามการโพสต์ของ hobodave: "ตั้งค่าเป็นค่าว่างถ้าสคริปต์ถูกสอบถามผ่านโปรโตคอล HTTPS"

if (!empty($_SERVER['HTTPS']))
{
    $secure_connection = true;
}

ทำมัน(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
Tivie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.