จะทำให้ file_get_contents () ทำงานกับ HTTPS ได้อย่างไร


106

ฉันกำลังตั้งค่าการประมวลผลบัตรเครดิตและจำเป็นต้องใช้วิธีแก้ปัญหาสำหรับ CURL รหัสต่อไปนี้ใช้งานได้ดีเมื่อฉันใช้เซิร์ฟเวอร์ทดสอบ (ซึ่งไม่ได้เรียก URL SSL) แต่ตอนนี้เมื่อฉันทดสอบบนเซิร์ฟเวอร์ที่ใช้งานได้กับ HTTPS มันล้มเหลวโดยมีข้อความแสดงข้อผิดพลาด "ไม่สามารถเปิดสตรีม"

function send($packet, $url) {
  $ctx = stream_context_create(
    array(
      'http'=>array(
        'header'=>"Content-type: application/x-www-form-urlencoded",
        'method'=>'POST',
        'content'=>$packet
      )
    )
  );
  return file_get_contents($url, 0, $ctx);
}

คำตอบ:


89

ลองใช้สคริปต์ต่อไปนี้เพื่อดูว่ามี https wrapper สำหรับสคริปต์ php ของคุณหรือไม่

$w = stream_get_wrappers();
echo 'openssl: ',  extension_loaded  ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_export($w);

ผลลัพธ์ควรเป็นอย่างนั้น

openssl: yes
http wrapper: yes
https wrapper: yes
wrappers: array(11) {
  [...]
}

@volker นั่นคือเหตุผลที่ฉันขอ allow_url_fopen
Gordon

สิ่งที่แปลกคือมันบอกว่า openssl ปิดอยู่ แต่ตาม phpinfo () มันถูกคอมไพล์ด้วยเว้นแต่ฉันจะเห็นว่ามันผิด
James Simpson

phpinfo () บอกคุณอย่างนั้นในรายการ config-line หรือมีทั้งส่วนที่เรียกว่า "OpenSSL"?
VolkerK

โอเคมันอยู่ในบรรทัดการกำหนดค่าไม่ใช่ส่วนสำหรับมัน ฉันเดาว่านั่นคือปัญหา?
James Simpson

ฉันมีทั้งหมดนั้นและยังใช้ไม่ได้ และ allow_url_fopen เฉพาะ URL ที่ไม่ใช่ https เท่านั้นที่ทำงานจาก localhost
Curtis

116

ในการอนุญาต https wrapper:

  • php_opensslนามสกุลต้องมีอยู่และสามารถเปิดใช้งาน
  • allow_url_fopen ต้องตั้งค่าเป็น on

ในไฟล์ php.ini คุณควรเพิ่มบรรทัดนี้หากไม่มี:

extension=php_openssl.dll

allow_url_fopen = On

ทั้งสองถูกตั้งค่าเป็นเปิดในการติดตั้งของฉัน แต่ฉันยังคงได้รับข้อผิดพลาด SSL "คำเตือน: file_get_contents (): SSL: Handshake หมดเวลาใน"
Adamantus

53

ลองทำดังต่อไปนี้

function getSslPage($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_REFERER, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

หมายเหตุ: การตรวจสอบการปิดการใช้งาน SSL หมายถึงการรักษาความปลอดภัยที่นำเสนอโดย HTTPS จะหายไป ใช้รหัสนี้สำหรับการทดสอบ / การพัฒนาในพื้นที่เท่านั้นห้ามใช้อินเทอร์เน็ตหรือเครือข่ายสาธารณะอื่น ๆ หากรหัสนี้ใช้งานได้หมายความว่าใบรับรอง SSL ไม่น่าเชื่อถือหรือไม่สามารถยืนยันได้ซึ่งคุณควรพิจารณาเพื่อแก้ไขเป็นปัญหาแยกต่างหาก


29
เหตุใดคุณจึงปิดการใช้งานการยืนยัน ssl เมื่อจัดการกับการประมวลผลบัตรเครดิต
ปีเตอร์

ขอบคุณเคล็ดลับอยู่ที่นี่: curl_setopt ($ ch, CURLOPT_SSL_VERIFYPEER, FALSE);
Dylan B

46
$url= 'https://example.com';

$arrContextOptions=array(
      "ssl"=>array(
            "verify_peer"=>false,
            "verify_peer_name"=>false,
        ),
    );  

$response = file_get_contents($url, false, stream_context_create($arrContextOptions));

สิ่งนี้จะช่วยให้คุณได้รับเนื้อหาจาก url ไม่ว่าจะเป็น HTTPS


ขอบคุณ! สิ่งนี้ได้ผลในตอนท้ายของฉัน พยายามโทรหา FB Open Graph API :)
decodingpanda

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

เยี่ยมมาก! ฉันพยายามดาวน์โหลดปฏิทิน airbnb บนไซต์ทดสอบ XAMPP เป็นเวลา 5 วันโดยใช้ file_get_contents ซึ่งช่วยแก้ปัญหาได้ขอบคุณ
JohnnyBeGood

ทำงานให้ฉันพยายามเชื่อมต่อกับช่องทดสอบ Vagrant โดยไม่มีใบรับรอง HTTP ที่ถูกต้องผ่าน https ลิงก์ไปยังตัวเลือกบริบท PHP SSL ถูกตั้งค่าที่นี่: php.net/manual/en/context.ssl.php ; ตรวจสอบเพื่อน = ต้องการการตรวจสอบใบรับรอง SSL ที่ใช้ Verify_peer_name = ต้องมีการยืนยันชื่อเพียร์
Anthony

นี่ไม่ใช่การทำลายการรับรอง SSL และเป็นช่องโหว่ด้านความปลอดภัยหรือไม่?
webchun

10

อาจเป็นเพราะเซิร์ฟเวอร์เป้าหมายของคุณไม่มีใบรับรอง SSL ที่ถูกต้อง


เซิร์ฟเวอร์ที่ร้องขอไม่จำเป็นต้องมีใบรับรอง SSL
ceejayoz

15
ฉันไม่ได้พูดเซิร์ฟเวอร์ที่ร้องขอฉันพูดว่าเซิร์ฟเวอร์เป้าหมาย
Emil Vikström

2
นั่นจะสอนให้ฉันอ่าน หึ! โปรดยอมรับคำขอโทษของฉันและโหวตให้คะแนน
ceejayoz

เซิร์ฟเวอร์เป้าหมายมีใบรับรอง SSL ที่ถูกต้อง
James Simpson

@ เจมส์คุณได้รับข้อผิดพลาดหรือไม่ถ้าคุณลองเชื่อมต่อกับ cURL แทน? หรือว่าเป็นไปไม่ได้ที่จะลอง?
Emil Vikström

6

เพียงเพิ่มสองบรรทัดในไฟล์ php.ini ของคุณ

extension=php_openssl.dll

allow_url_include = On

มันทำงานให้ฉัน


1
คุณอาจหมายถึงallow_url_fopenเนื่องจากคำถามเกี่ยวกับการเปิด url ซึ่งไม่รวมถึง
shukshin.ivan


5

HTTPS ได้รับการสนับสนุนโดยเริ่มจาก PHP 4.3.0 หากคุณได้รวบรวมเพื่อรองรับ OpenSSL ตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์เป้าหมายมีใบรับรองที่ถูกต้องไฟร์วอลล์อนุญาตการเชื่อมต่อขาออกและallow_url_fopenใน php.ini ถูกตั้งค่าเป็น true


ฉันมี PHP 5.2.8 พร้อมการรองรับ OpenSSL ฉันได้รับข้อผิดพลาดเดียวกันกับสิ่งนี้และเซิร์ฟเวอร์เป้าหมายมีใบรับรองที่ถูกต้อง
James Simpson

2
ไฟร์วอลล์ได้รับการกำหนดค่าให้อนุญาตการเชื่อมต่อ https ขาออกหรือไม่ โดยปกติแล้วเว็บเซิร์ฟเวอร์ที่ใช้ https จะไม่ทำงานบนพอร์ต 80 มีข้อผิดพลาดอื่นนอกเหนือจาก 'ล้มเหลวในการเปิดสตรีม' หรือไม่?
Gordon

1
เท่าที่ฉันรู้นี่เป็นข้อผิดพลาดทั้งหมด: คำเตือน: fopen (https: // ... ) [function.fopen]: ไม่สามารถเปิดสตรีม: ไม่มีไฟล์หรือไดเร็กทอรีดังกล่าวใน / home / user / public_html / test.php ทางสาย 993
James Simpson

และ allow_url_fopen ใน php.ini ตั้งค่าเป็นอะไร
Gordon

นั่นเป็นเรื่องแปลก คุณสามารถ GET บน HTTP และ URL HTTPS เพื่อดูว่าได้ผลหรือไม่ ไม่มีบริบทสตรีม?
Gordon

3

ในกรณีของฉันปัญหาเกิดจาก WAMP ใช้ php.ini สำหรับ CLI ที่แตกต่างจาก Apache ดังนั้นการตั้งค่าของคุณที่ทำผ่านเมนู WAMP จึงไม่ใช้กับ CLI เพียงแค่ปรับเปลี่ยน CLI php.ini ก็ใช้งานได้


1

บางครั้งเซิร์ฟเวอร์จะเลือกที่จะไม่ตอบสนองตามสิ่งที่เห็นหรือไม่เห็นในส่วนหัวคำขอ http (เช่นตัวแทนผู้ใช้ที่เหมาะสม) หากคุณสามารถเชื่อมต่อกับเบราว์เซอร์ให้จับส่วนหัวที่มันส่งและเลียนแบบในบริบทสตรีมของคุณ


0

ฉันติดอยู่กับ https ที่ใช้งานไม่ได้บน IIS แก้ไขด้วย:

file_get_contents ('https .. ) จะไม่โหลด

  • ดาวน์โหลดhttps://curl.haxx.se/docs/caextract.html
  • ติดตั้งภายใต้ ..phpN.N / extras / ssl
  • แก้ไข php.ini ด้วย:

    curl.cainfo = "C: \ Program Files \ PHP \ v7.3 \ extras \ ssl \ cacert.pem" openssl.cafile = "C: \ Program Files \ PHP \ v7.3 \ extras \ ssl \ cacert.pem"

ในที่สุด!


-1

เพื่อตรวจสอบว่ามี URL หรือไม่

รหัสในคำถามของคุณสามารถเขียนใหม่เป็นเวอร์ชันที่ใช้งานได้:

function send($packet=NULL, $url) {
// Do whatever you wanted to do with $packet
// The below two lines of code will let you know if https url is up or not
$command = 'curl -k '.$url;
return exec($command, $output, $retValue);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.