GETリクエストのボディはPHPで取得できるの?試してみた
定期的に業務で不正なリクエストがないか見ています。 その調査でふと、PHPはGETリクエストに含まれるボディの値が取得できてしまうのか、 取得可能であればそこも気にしなければなぁ、ということで調べてみました。
GETリクエストのボディ?
GETは指定したURIの情報を取得するためのもので、通常ボディは含めませんが、やろうと思えば指定は可能です。
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
https://tools.ietf.org/html/rfc7231#section-4.3.1
RFCでも、特にダメですとは言われてはいない。 一部、リクエストを拒否する既存の実装があるかもね。くらい
環境
まずは、スーパーグローバル変数 $GET $POST $_REQUEST で確認
PHPファイルを用意する
以下のように、$GET, $POST, $_REQUESTで受け取れるPHPファイルを用意しました。
<?php echo "\$_GET query_param: " . $_GET["query_param"] . "¥n"; echo "\$_GET body_param: " . $_GET["body_param"] . "¥n"; echo "\$_POST query_param: " . $_POST["query_param"] . "¥n"; echo "\$_POST body_param: " . $_POST["body_param"] . "¥n"; echo "\$_REQUEST query_param: " . $_REQUEST["query_param"] . "¥n"; echo "\$_REQUEST body_param: " . $_REQUEST["body_param"] . "¥n";
リクエストを準備する
POSTリクエスト
POST /index.php?query_param=hoge HTTP/1.1 Host: www.example.com:8888 Content-Type: application/x-www-form-urlencoded Origin: http://www.example.com:8888 Content-Length: 9 body_param=huga
GETリクエスト(body付き)
GET /index.php?query_param=hoge HTTP/1.1 Host: www.example.com:8888 Content-Type: application/x-www-form-urlencoded Origin: http://www.example.com:8888 Content-Length: 9 body_param=huga
まずは、POSTリクエストの結果
HTTP/1.1 200 OK Server: nginx/1.15.12 Date: Sun, 14 Jun 2020 03:02:41 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/7.3.11 Content-Length: 143 $_GET query_param: hoge $_GET body_param: $_POST query_param: $_POST body_param: huga $_REQUEST query_param: hoge $_REQUEST body_param: huga
- $_GETでリクエストBobyの値は取れませんでした。
- $_POSTでクエリパラメータの値は取れませんでした。
まずは、予想通り
続いて今回確認したかった、GETリクエストの結果
HTTP/1.1 200 OK Server: nginx/1.15.12 Date: Sun, 14 Jun 2020 03:07:42 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/7.3.11 Content-Length: 135 $_GET query_param: hoge $_GET body_param: $_POST query_param: $_POST body_param: $_REQUEST query_param: hoge $_REQUEST body_param:
このようになりました。 GETメソッドが来た場合は、$GET, $POST, $_REQUESTではリクエストbodyの値は取得できないことがわかりました。
php://input を使ってみる
php://input は読み込み専用のストリームで、 リクエストの body 部から生のデータを読み込むことができます。
https://www.php.net/manual/ja/wrappers.php.php
これを使ってみます。
PHPファイルを用意
<?php $hoge = file_get_contents('php://input'); echo $hoge;
リクエストを準備する
先ほどと同じやつです。
GET /index.php?query_param=hoge HTTP/1.1 Host: www.example.com:8888 Content-Type: application/x-www-form-urlencoded Origin: http://www.example.com:8888 Content-Length: 15 body_param=huga
結果
HTTP/1.1 200 OK Server: nginx/1.15.12 Date: Sun, 14 Jun 2020 03:14:09 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/7.3.11 Content-Length: 15 body_param=huga
リクエストボディの値が、そのままの形で取得できました! (POST, PUT, PATCH, DELETEでも確認してみましたが、結果は同じでした。)
まとめ
- $GET $POST $_REQUEST では、GETリクエストのボディに含まれる値は取得できない
php://input
を使うと、GETリクエストのボディに含まれる値はそのままの形で取得できる- おそらく、HTTPのメソッド関係なく取得できるものと思われます
ということがわかりました〜。
以上