解決PHP5.6及7~ stream_socket_client() 函數問題
Warning: stream_socket_client(): Peer certificate CN=’ *****.com’ did not match expected CN=’ *****’
相信有使用到 stream_context_create() 及 stream_socket_client() 來建立ssl連線的人,可能在 PHP5.6 及 7 以上版本有遇到程式回報Warning: stream_socket_client(): Peer certificate的問題,尤其是使用第三方的library需要ssl連線,且library可能尚未更新或是無法支援時。
若遇到這種問題可以先確認程式分別在 php5.6 及 7 以上的運作是否正常,因為雖然回報的錯誤訊息是一樣的,但是會有兩種問題原因,不過其實都是與peer_name有關!
所以我們若要搞清楚問題點的話,需要先在環境中安裝 php5.6 及 7。
可以先分成 php5.6 及 7 以上都無法運作 以及 php5.6 運作正常但 7 以上無法運作
我們先來看看php官方與ssl有關的文件說明:
我們會直接看到
- peer_name string
Peer name to be used. If this value is not set, then the name is guessed based on the hostname used when opening the stream.
- verify_peer boolean
Require verification of SSL certificate used.
Defaults to TRUE.
- verify_peer_name boolean
Require verification of peer name.
Defaults to TRUE.
- CN_match string
Common Name we are expecting. PHP will perform limited wildcard matching. If the Common Name does not match this, the connection attempt will fail.
Note: This option is deprecated, in favour of peer_name, as of PHP 5.6.0.
官方文件最後也說明到
Changelog
Version |
Description |
5.6.0 |
Added peer_fingerprint and verify_peer_name. verify_peer default changed to TRUE. |
所以我們知道官方在 php5.6 之後,把 verify_peer_name. verify_peer 這兩個選項更改為預設開啟,並且將 CN_match 棄用,以 peer_name 替代。
但 php5.6 時 CN_match 及 peer_name 其實都可以使用,php7 以上才正式將 CN_match 棄用,就算設定了也會無效,需改為使用 peer_name 唷!
1. php5.6及7以上都無法運作
如果是這個情況表示,可能是因為原本程式碼中socket option沒有設定 verify_peer_name, verify_peer ,這兩個選項其中之一,或是兩個都都沒有設定。
所以因為php5.6之後這兩個選項預設開啟的緣故,使ssl連線會去驗證 SSL certificate 及 peer name 而造成錯誤。
這時我們只要先確認程式碼中,是不是哪一個沒設定,我們只要加上去並設定為 0 或是 false 就行囉!
eg.
$socket_opts = array( 'verify_peer' => 0, 'verify_peer_name' => 0, 'allow_self_signed' => 0, 'cafile' => $CAFile ); $context = stream_context_create ( array ('ssl' => $socket_opts)); $conn=stream_socket_client('ssl://'.$HOST.':'.$PORT,$Errnum,$Errstr,$Timeout,STREAM_CLIENT_CONNECT,$context);
2. php5.6運作正常但7以上無法運作
若是這種情況,很可能就是因為 php5.6 時 CN_match及peer_name,其實都可以使用,php7 以上才正式將 CN_match 棄用,就算設定了也會無效這個問題,我們只要改為使用 peer_name 就可以解決囉!
eg.
$socket_opts = array( 'peer_name' => 'xxxx.xxxx.com', 'verify_peer' => 0, 'allow_self_signed' => 0, //'CN_match' => 'xxxx.xxxx.com', //7.0以上取消這個選項改為使用'peer_name' 'cafile' => $CAFile ); $context = stream_context_create ( array ('ssl' => $socket_opts)); $conn=stream_socket_client('ssl://'.$HOST.':'.$PORT,$Errnum,$Errstr,$Timeout,STREAM_CLIENT_CONNECT,$context);
若想了解更多關於Magento的相關教學,或追蹤我們的Facebook粉絲專頁,跟著我們歐斯瑞一起學習吧!
我要留言