さくらのレンタルサーバのリクエストヘッダが何かおかしい
さくらのレンタルサーバは、2018年3月以降の仕様変更でPHPモジュールモードの利用が出来るようになり、特にWordPressの動作は高速化されています。
それ以前のレンタルサーバとでは、仕様が大幅に変わっているため自動的には新仕様にはバージョンアップされず、新たにレンタルサーバを契約し直さないといけません。
今回、新仕様のレンタルサーバに乗り換えてからプログラムの挙動がおかしくなり、今まで動いていたPHPが動かなくなった原因と解決策を公開します。
1. 問題発生
旧仕様のレンタルサーバで動いていたsakura.io用のPHPプログラムが、新仕様のレンタルサーバでは何故か動かない。
2. 発生条件
旧仕様のレンタルサーバでは、HTTP、HTTPSの両方とも動くが、新仕様のレンタルサーバではHTTPSのみ動かない。
3. リクエストヘッダを比較してみる
※ホスト名とX-Sakura-Signatureの部分は書き換えています。
■旧仕様のレンタルサーバ:HTTP
[26-Aug-2019 22:04:20 Asia/Tokyo] Array
(
[Host] => example.jp
[X-Real-Ip] => 153.120.162.52
[X-Forwarded-Proto] => http
[Listen-Ipaddr] => 210.224.185.35
[Content-Length] => 172
[User-Agent] => SAKURA-IoT-Webhook
[Content-Type] => application/json
[X-Sakura-Signature] => xxxxxxxxxxxxxxxxxxxxxxxxxx
[Accept-Encoding] => gzip
)
■旧仕様のレンタルサーバ:HTTPS
[26-Aug-2019 22:04:59 Asia/Tokyo] Array
(
[Host] => example.jp
[X-Real-Ip] => 153.120.162.52
[X-Forwarded-Proto] => https
[X-Sakura-Forwarded-For] => 153.120.162.52
[Listen-Ipaddr] => 210.224.185.35
[Content-Length] => 175
[X-Sakura-Signature] => xxxxxxxxxxxxxxxxxxxxxxxxxx
[Content-Type] => application/json
[User-Agent] => SAKURA-IoT-Webhook
[Accept-Encoding] => gzip
)
■新仕様のレンタルサーバ:HTTP
[26-Aug-2019 21:29:46 Asia/Tokyo] Array
(
[Host] => example.jp
[X-Real-IP] => 153.120.162.52
[X-Forwarded-Proto] => http
[LISTEN-IPADDR] => 202.181.99.80
[Content-Length] => 173
[User-Agent] => SAKURA-IoT-Webhook
[Content-Type] => application/json
[X-Sakura-Signature] => xxxxxxxxxxxxxxxxxxxxxxxxxx
[Accept-Encoding] => gzip
)
■新仕様のレンタルサーバ:HTTPS
[26-Aug-2019 21:29:25 Asia/Tokyo] Array
(
[Host] => example.jp
[X-Real-IP] => 153.120.162.52
[X-Forwarded-Proto] => https
[X-SAKURA-FORWARDED-FOR] => 153.120.162.52
[LISTEN-IPADDR] => 202.181.99.80
[Content-Length] => 175
[content-type] => application/json
[user-agent] => SAKURA-IoT-Webhook
[x-sakura-signature] => xxxxxxxxxxxxxxxxxxxxxxxxxx
[accept-encoding] => gzip
)
なんだこれ、HTTPSのみ「x-sakura-signature」などリクエストヘッダのキー文字列が小文字に置換されてしまっております。しかも大文字小文字が混在しておりルールが統一されておらず何か変。
if($header_ary['X-Sakura-Signature'] === hash_hmac('sha1' , $json , SAKURAIO_SECRET)){
//正しい署名
}
署名を検証するために、こんなコード書いていたので動かなかったようです…。
if(!empty($header_ary['X-Sakura-Signature'])){
$sakura_signature = $header_ary['X-Sakura-Signature'];
} elseif(!empty($header_ary['x-sakura-signature'])){
$sakura_signature = $header_ary['x-sakura-signature'];
} else{
$sakura_signature = "";
}
暫定対応として、上記の処理を追加、さくらのサポートに連絡してみよう…。
(追記1)2019-8-27
リクエストヘッダの大文字小文字が統一されていない事を前提にして、array_change_key_case() 関数でキーを小文字に統一すれば良いという情報を貰ったので。
//---リクエストヘッダ配列のすべてのキーを小文字に変換
$header_ary = array_change_key_case($header_ary);
if($header_ary['x-sakura-signature'] === hash_hmac('sha1' , $json , SAKURAIO_SECRET)){
//正しい署名(小文字)
}
こんな感じに修正しました。PHP何でもある。すごい。
(追記2)2019-8-28
さくらインターネットのサポートより返答あり。
新仕様のさくらのレンタルサーバでは、HTTPSアクセスで高速なHTTP/2を利用できるようになり。HTTP/2の仕様上ヘッダが小文字になるとの事でした。
さくらのレンタルサーバの独自実装の部分のヘッダーは、小文字にはならないので大文字小文字が混在しているように見えるようです。
この仕様変更を機にHTTP/HTTPSの両方すべてを小文字に統一してくれた方が分かりやすい気がします。