テックブログ

  1. Laravel
  2. 598 view

Laravelで爆速API開発シリーズ「認可編」

Laravelで爆速API開発シリーズ第四弾は「認可」です!APIを外部に公開する時、あるデータへのアクセス制御は非常に重要になってきますので、Laravelのポリシーを用いた認可の実装を紹介します。本記事はLaravelで爆速API開発シリーズ「RESTful API編」の続きなので未読の方はぜひチェックしてください!またLaravelで爆速API開発シリーズ「JWTユーザログイン編」でJWT認証についても解説しているのでぜひチェックしてください!

やること

Laravelで爆速API開発シリーズ「RESTful API編」で作成したToDoにアクセス制限をつけます。

具体的にはログインユーザのみに新規作成を許可し、更新、削除に関してはToDoを作成したユーザのみに許可するようにします。

ポリシーとは

ポリシーとは特定のモデルやリソースに関する認可ロジックを系統立てるためのクラスです。たとえば、今回の場合ToDoアプリケーションの場合、Todoモデルとそれに対応する、Todoを作成、更新するなどのユーザーアクションを認可するTodoPolicyを作成します。

ポリシーの作成

さっそくArtisanコマンドを使ってポリシーを作成します。

php artisan make:policy TodoPolicy --model=Todo

app/PoliciesにTodoPolicy.phpが作成されたのを確認しましょう。
以下のようになっているはずです。

<?php

namespace App\Policies;

use App\User;
use App\Todo;
use Illuminate\Auth\Access\HandlesAuthorization;

class TodoPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view the todo.
     *
     * @param  \App\User  $user
     * @param  \App\Todo  $todo
     * @return mixed
     */
    public function view(User $user, Todo $todo)
    {
        //
    }

    /**
     * Determine whether the user can create todos.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        //
    }

    /**
     * Determine whether the user can update the todo.
     *
     * @param  \App\User  $user
     * @param  \App\Todo  $todo
     * @return mixed
     */
    public function update(User $user, Todo $todo)
    {
        //
    }

    /**
     * Determine whether the user can delete the todo.
     *
     * @param  \App\User  $user
     * @param  \App\Todo  $todo
     * @return mixed
     */
    public function delete(User $user, Todo $todo)
    {
        //
    }
}

ポリシーの登録

AuthServiceProviderにはEloquentモデルと対応するポリシーをマップするためのpoliciesプロパティがあります。ここに先ほど作成したTodoPolicyを登録しましょう。以下のようにします。

app/Providers/AuthServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Todo' => 'App\Policies\TodoPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

Eloquentリレーションの定義

app/User.phpに以下を記述しましょう。

public function todos()
    {
        return $this->hasMany('App\Todo');
    }
}

app/Todo.phpに以下を記述します。

public function user()
  {
      return $this->belongsTo('App\User');
  }

これでUserとTodoの間に一対多の関係を定義することができました。

ポリシーの記述

TodoPolicyの記述をしましょう。

public function update(User $user, Todo $todo)
    {
        return $user->id === $todo->user_id;
    }

public function delete(User $user, Todo $todo)
    {
        return $user->id === $todo->user_id;
    }

書き上げたらPolicyを適用します。

TodoController.phpにconstructorを追加しましょう。

public function __construct(){
      $this->middleware('jwt.auth')->only('store','update', 'destroy');
      $this->middleware('can:update,todo')->only('update');
      $this->middleware('can:delete,todo')->only('destroy');
    }


public function store(Request $request)
    {
        $todo = new Todo;
        $todo->title = $request->title;
        $todo->status = $request->status;
        $todo->memo = $request->memo;
        $todo->user_id = Auth::id(); // この行を追加
        $todo->save();
        return $todo;
    }
  • todoのテーブルにuser_idのカラムを追加してください。

これで非ログインユーザは新規追加、更新、削除ができなくなり、更新、削除に関してはTodoを所有するユーザ以外はできなくなりました。

POSTMANで動作検証

例えば、以下のようにリクエストすると401 Unauthorizedとなります。

以下のようにトークンを取得しましょう。(JWTトークンに関してはLaravelで爆速API開発シリーズ「JWTユーザログイン編」を参考にしてください。)


のようにリクエストするとTodoが更新されるようになりました。

更新や削除はTodoの所有ユーザでしかできないのを確認しましょう。

いかがでしたでしょうか。LaravelのPolicyを使うことによって認可ロジックを綺麗で簡潔に表現できます。実際のアプリケーションではもう少し複雑な認可ロジックを組み立てる必要がありますが、この記事で基本をマスターして応用していきましょう!

お疲れ様です〜。

The following two tabs change content below.

riri

半年おきくらいにバックエンドとフロントエンドを行ったり来たり。 25歳。 将棋好き。

Laravelの最近記事

  1. Laravel HorizonでQueue/Jobを眺める

  2. LaravelでRedisとSupervisorを導入してQueue/Jobを扱う【doc…

  3. Laravelの環境(Nginx+MySQL+PHP)をdocker-composeでイチ…

  4. Laravel5.6で掲示板システムを作るチュートリアル

  5. Laravel+Nginx+phpMyAdminをlaradockで環境構築

関連記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。