環境
Laravel10のLaravel Sail
routes/web.phpで設定した、authミドルウェアを適用していないAPI
routes/web.php
Route::post('/ping', function() {
return response()->json(['message' => 'pong']);
});
HTTPリクエストヘッダにトークンを含めなかった場合
http://localhost へアクセスしChromeのデベロッパーツールから次のJSコードを実行。
responsePing = await fetch('http://localhost/ping', { method: 'POST' });
結果として、HTTPレスポンスステータスコード419が返ってきて、CSRF関連のエラーとなる。
HTTPリクエストヘッダにX-XSRF-TOKEN を含めた場合
http://localhost へアクセスしChromeのデベロッパーツールから次のJSコードを実行。
// XSRF-TOKENの値を取得。
var re = new RegExp('^XSRF-TOKEN=');
var xsrfToken = document.cookie.replace(re, '');
xsrfToken = decodeURIComponent(xsrfToken);
// HTTPリクエストのヘッダにX-XSRF-TOKENを設定。
var headers = new Headers();
headers.set('X-XSRF-TOKEN', xsrfToken);
// fetchメソッドの引数まとめ。
var paramsPing = {
method: 'POST',
headers
};
var responsePing = await fetch('http://localhost/ping', paramsPing);
結果として、{“message”: “pong”} というJSONが返ってくる。
HTTPリクエストヘッダにX-CSRF-TOKEN を含めた場合
HTMLのヘッダ内にcsrf-tokenの値を保持するmetaタグがあるページにアクセスし、
Chromeのデベロッパーツールから次のJSコードを実行。
// CSRF-TOKENの値を取得。
var csrfToken = document.head.querySelector('[name="csrf-token"]').content;
// HTTPリクエストのヘッダにX-CSRF-TOKENを設定。
var headers = new Headers();
headers.set('X-CSRF-TOKEN', csrfToken);
// fetchメソッドの引数まとめ。
var paramsPing = {
method: 'POST',
headers
};
var responsePing = await fetch('http://localhost/ping', paramsPing);
var resultJson = await responsePing.json();
結果として、{“message”: “pong”} というJSONが返ってくる。
routes/web.php で設定した、authミドルウェアを適用したAPI
routes/web.php
Route::middleware('auth')->post('/ping', function() {
return response()->json(['message' => 'pong']);
});
フロント・画面からログイン後、HTTPリクエストヘッダにトークンを含めなかった場合
Chromeのデベロッパーツールから次のJSコードを実行。
responsePing = await fetch('http://localhost/ping', { method: 'POST' });
結果として、HTTPレスポンスステータスコード419が返ってきて、CSRF関連のエラーとなる。
フロント・画面からログイン後、HTTPリクエストヘッダにX-XSRF-TOKEN を含めた場合
Chromeのデベロッパーツールから次のJSコードを実行。
// XSRF-TOKENの値を取得。
var re = new RegExp('^XSRF-TOKEN=');
var xsrfToken = document.cookie.replace(re, '');
xsrfToken = decodeURIComponent(xsrfToken);
// HTTPリクエストのヘッダにX-XSRF-TOKENを設定。
var headers = new Headers();
headers.set('X-XSRF-TOKEN', xsrfToken);
// fetchメソッドの引数まとめ。
var paramsPing = {
method: 'POST',
headers
};
var responsePing = await fetch('http://localhost/ping', paramsPing);
結果として、{“message”: “pong”} というJSONが返ってくる。
フロント・画面からログイン後、HTTPリクエストヘッダにX-CSRF-TOKEN を含めた場合
HTMLのヘッダ内にcsrf-tokenの値を保持するmetaタグがあるページにアクセスし、
Chromeのデベロッパーツールから次のJSコードを実行。
// CSRF-TOKENの値を取得。
var csrfToken = document.head.querySelector('[name="csrf-token"]').content;
// HTTPリクエストのヘッダにX-CSRF-TOKENを設定。
var headers = new Headers();
headers.set('X-CSRF-TOKEN', csrfToken);
// fetchメソッドの引数まとめ。
var paramsPing = {
method: 'POST',
headers
};
var responsePing = await fetch('http://localhost/ping', paramsPing);
var resultJson = await responsePing.json();
結果として、{“message”: “pong”} というJSONが返ってくる。
非ログイン状態で、HTTPリクエストヘッダにX-CSRF-TOKEN を含めた場合
HTMLのヘッダ内にcsrf-tokenの値を保持するmetaタグがあるページにアクセスし、
Chromeのデベロッパーツールから次のJSコードを実行。
// CSRF-TOKENの値を取得。
var csrfToken = document.head.querySelector('[name="csrf-token"]').content;
// HTTPリクエストのヘッダにX-CSRF-TOKENを設定。
var headers = new Headers();
headers.set('X-CSRF-TOKEN', csrfToken);
// fetchメソッドの引数まとめ。
var paramsPing = {
method: 'POST',
headers
};
var responsePing = await fetch('http://localhost/ping', paramsPing);
var resultJson = await responsePing.json();
結果として、HTTPレスポンスステータスコード302が返ってきて、ログイン画面へリダイレクトされる。
routes/api.php で設定したAPI(SanctumのSPA認証)
routes/api.php
// ログイン処理。
// email=name1@aa.com
// password=password
// でログインできるアカウントがあることを前提とする。
Route::post('/login', function(Request $request) {
if (\Illuminate\Support\Facades\Auth::attempt($request->all())) {
return response()->json(['result' => 'correct']);
}
return response()->json(['result' => 'incorrect']);
});
// ログイン済みでないとJSONを取得できない。
Route::middleware('auth:sanctum')->post('/ping', function() {
return response()->json(['message' => 'pong']);
});
JSコード
http://localhost へアクセスしChromeのデベロッパーツールから次のJSコードを実行。
// CSRF保護初期化。
var headers = new Headers();
headers.set('Accept', 'application/json');
headers.set('Origin', 'http://localhost');
var paramsGet = {
method: 'GET',
headers
};
var responseCsrf = await fetch('http://localhost/sanctum/csrf-cookie', paramsGet);
// loginAPIをコール。
// 取得したXSRF-TOKENをHTTPリクエストヘッダへ追加。
var re = new RegExp('^XSRF-TOKEN=');
var xsrfToken = document.cookie.replace(re, '');
xsrfToken = decodeURIComponent(xsrfToken);
headers.set('X-XSRF-TOKEN', xsrfToken);
// ログイン用パスパラメータの設定。
var formData = new FormData();
formData.append('email', 'name1@aa.com');
formData.append('password', 'password');
var paramsPostData = {
method: 'POST',
headers,
body: formData
};
var responseLogin = await fetch('http://localhost/api/login', paramsPostData);
// pingAPIをコール
var xsrfToken = document.cookie.replace(re, '');
xsrfToken = decodeURIComponent(xsrfToken);
headers.set('X-XSRF-TOKEN', xsrfToken);
var paramsPost = {
method: 'POST',
headers
};
var responsePing = await fetch('http://localhost/api/ping', paramsPost);
var resultJson = await responsePing.json();
結果として、{“message”: “pong”} というJSONが返ってくる。