LaravelでのAPIの挙動を確認(トークン認証以外)

環境

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が返ってくる。

コメント

タイトルとURLをコピーしました