引き続きCORSのまとめをやっていきたいと思います。今回は認証情報を含むリクエストに関してです。それではさっそく見ていきます!
withCredentialsプロパティ
デフォルトではクロスオリジンに対するリクエストにHTTP認証やクッキーなどの認証に用いられるリクエストヘッダは自動的に送信されません。これらを用いるためにはXMLHttpRequestのwithCredentialsプロパティをtrueでセットする必要があります。
withCredentialsプロパティをセットしない場合
まずはセットしない場合のサーバーとのやりとりを見ていきます。
GET http://example.jp/33/33-005.html HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://example.jp/33/
Upgrade-Insecure-Requests: 1
Host: example.jp
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Wed, 05 May 2021 23:34:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 408
Connection: keep-alive
Last-Modified: Mon, 14 May 2018 13:08:18 GMT
ETag: "198-56c2a2decfddb-gzip"
Accept-Ranges: bytes
Vary: Accept-Encoding
X-UA-Compatible: IE=edge
<body>
<script>
var req = new XMLHttpRequest();
req.open('GET', 'http://api.example.net/33/33-006.php');
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var span = document.getElementById('counter');
span.textContent = req.responseText;
}
};
req.send(null);
</script>
呼び出しカウンター:<span id="counter"></span>
</body>
GET http://api.example.net/33/33-006.php HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://example.jp
Connection: keep-alive
Referer: http://example.jp/
Host: api.example.net
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Wed, 05 May 2021 23:34:34 GMT
Content-Type: application/json
Content-Length: 11
Connection: keep-alive
Set-Cookie: PHPSESSID=jrpe1qbb85250e8m6ts9pes4j3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Access-Control-Allow-Origin: http://example.jp
X-UA-Compatible: IE=edge
{"count":1}
サーバーはSet-Cookieヘッダでクッキーをセットしようとしていることが分かります。ブラウザにクッキーがセットされているか確認するためリロードしてリクエストヘッダーを確認します。
GET http://api.example.net/33/33-006.php HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://example.jp
Connection: keep-alive
Referer: http://example.jp/
Cache-Control: max-age=0
Host: api.example.net
クッキーがセットされていないことが分かります。
withCredentialsプロパティをセットする場合
今度はwithCredentialsプロパティをセットしてクロスオリジンへリクエストを投げてみます。
var req = new XMLHttpRequest();
req.open('GET', 'http://api.example.net/33/33-006.php');
req.withCredentials = true; # 追記
今度はブラウザのコンソールでエラーが置きました。
クロスオリジン要求をブロックしました: 同一生成元ポリシーにより、http://api.example.net/33/33-006.php にあるリモートリソースの読み込みは拒否されます (理由: CORS ヘッダー ‘Access-Control-Allow-Credentials’ は ‘true’ であるべき)。
withCredentialsプロパティをtrueにしたリクエストでは、サーバーはAccess-Control-Allow-Credentials: trueというヘッダーを返さなければなりません。
最後にレスポンスヘッダーをセットし、正しくクッキーがセットされたやりとりを見ておきます。
GET http://api.example.net/33/33-006b.php HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://example.jp
Connection: keep-alive
Referer: http://example.jp/
Host: api.example.net
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Wed, 05 May 2021 23:51:34 GMT
Content-Type: application/json
Content-Length: 11
Connection: keep-alive
Set-Cookie: PHPSESSID=1aaucob4d3qsqtgas69tdnfch2; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Access-Control-Allow-Origin: http://example.jp
Access-Control-Allow-Credentials: true
X-UA-Compatible: IE=edge
{"count":1}
リロードしてみると、クッキーがセットされているのが分かります。
GET http://api.example.net/33/33-006b.php HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://example.jp
Connection: keep-alive
Referer: http://example.jp/
Cookie: PHPSESSID=1aaucob4d3qsqtgas69tdnfch2
Cache-Control: max-age=0
Host: api.example.net
- XMLHttpRequestオブジェクトのwithCredentialsプロパティをtrueにする
- レスポンスヘッダとしてAccess-Control-Allow-Credentials: trueを返す
さいごに
認証を含むリクエストの場合、プロパティを変更したりヘッダーをセットしたりと色々なことをしないといけないことが分かりました。今後、自分で認証を実装するときはこういうことに気をつけたいと思いました。
ここまで読んでいただきありがとうございました。