🗂

Laravel AuditingでRESTful API(JWT認証)をばっちり監視

2023/12/30に公開

記事の目的

本記事では、Laravel 10を使用し、JWT認証を取り入れたステートレスなAPI実装における、
Laravel Auditingの取り扱い方について解説します。

Laravel Auditingとは

Laravel Auditingはデータベースのレコードが作成、更新、削除されるたびに、これらの変更を自動的に記録してくれます。これにより、後で何が起こったかを正確に確認することができるので、バグの追跡やセキュリティ監査にも役立ちます。

セットアップ方法

インストール

composerを使用します。

composer require owen-it/laravel-auditing

プロバイダーに追加

インストール後にconfig/app.phpにproviderを追加してください。

config/app.php
'providers' => [
	// ...
+       OwenIt\Auditing\AuditingServiceProvider::class,
	// ...
],

設定ファイル作成

プロバイダを追加後、以下コマンドで設定ファイルを作成します。

php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="config"

テーブルを作成

保存先のマイグレーションファイルを作成します。

php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="migrations"

auditsテーブルのuser_idがintegerで定義されているので、必要に応じて変更してください。

XXXX_create_audits_table.php
class CreateAuditsTable extends Migration
{
	public function up()
	{
-			$table->unsignedBigInteger($morphPrefix . '_id')->nullable();
+			$table->string($morphPrefix . '_id')->nullable();
		});
	}
}

今回user_id(jwtのsub)はstring型なので上記のように変更します。
そののちにartisanコマンドを実行し、auditsテーブルを作成してください

php artisan migrate

監視手順

セットアップが完了したら、次は実際にデータを監視する方法に入りますが、ステートレスなAPIの実装において、公式ドキュメント通りの実装を行うと、CRUD実行後のauditsテーブルには、user_idが格納されません。そのため、少々工夫が必要になります。

$requestにユーザーIDを付加

ミドルウェアを用いてJWT認証を行いますが、JWTをデコードした際に格納されるsubと呼ばれるユーザー識別子をHTTPリクエストオブジェクトである$requestに付加します。

VerfyJwtMiddleware.php
$request->attributes->add(['jwt_sub' => $decode->sub]);

JWT認証のほかにも、ログイン状態でないが、操作したユーザーのIDを格納したい場合には上記のように、リクエストに属性を付加してください。

トレイトを作成

トレイトは、複数のクラスで共通の機能を再利用したい場合に役立つ仕組みです。今回は、Auditingのトレイトにデフォルトで定義されてあるtransformAuditというメソッドをオーバーライドする必要があるので、下記のようなカスタムトレイトを作成します。

<?php

namespace App\Traits;

trait AuditableCustom
{
	public function transformAudit(array $data): array
	{
		$data['user_id'] = request()->attributes->get('jwt_sub');
		return $data;
	}
}

先ほどrequestに設定した属性を取得し、user_idに格納します。

監視設定

データの監視を行う際は、対象のModelに対して下記のような設定を加えます。

具体例

test.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
+ use OwenIt\Auditing\Auditable;
+ use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
+ use App\Traits\AuditableCustom;

+ class Test extends Model implements AuditableContract
- class Test extends Model
{
+	use Auditable, AuditableCustom {
+		AuditableCustom::transformAudit insteadof Auditable;
+	}

AuditableCustomトレイト内のtransformAuditメソッドを使用し、Auditableトレイト内の同名のメソッドは無視するように指定しています。

監視結果

監視結果は以下のような形で出力されます。(一部省略しています)

id user_type user_id event auditable_type auditable_id old_values new_values url ip_address user_agent tags created_at updated_at
2 P-AOoO2LsTgbL3338uNs6ewa3gUUdo created App\Models\Test 0 省略 省略 省略 省略 省略 2023-12-27 07:55:30 2023-12-27 07:55:30
3 P-AOoO2LsTgbL3338uNs6ewa3gUUdo updated App\Models\Test 0 省略 省略 省略 省略 省略 2023-12-27 07:56:03 2023-12-27 07:56:03

出力する情報のカスタマイズ等行えるので、ぜひとも使ってみて下さい。

Discussion