Laravel Sanctumの使い方(フロントエンド編)

nuxt.js Laravel

本記事では、掲示板アプリを想定して、ユーザー登録とログインのサンプルコードと解説を載せています。
サンプルコードについては、完全版ではなく検証程度のものです。

sanctumで作ったバックエンドに対して、axiosを使用して処理する時の雰囲気がわかるかと思います。
バックエンドは前回の記事で作成しましたので、下記を参照してください。
Laravel Sanctumの使い方(バックエンド編)
Laravel Sanctumを使って、認証を実装してみました。 バックエンドがLaravelでフロントエンドがNuxt.jsの構成です。 本記事では、Laravel Sanctumの導入から、ユーザー登録APIとログインAPIを作成すると...

フロントのSPAはNuxt.jsでvuetifyを使用して作っています。

※ユーザー登録と同じように処理するため掲示板投稿のコードについては省略しています。
ファイルの配置場所などの詳細については、後述するgithubのコードを確認してください。

Nuxt環境の準備

プロジェクトを作成する

まずcreate-nuxt-appを使用して、プロジェクトの環境を準備します。
プロジェクトの作成方法については、下記を参照してください。

yarnでライブラリをインストールする

次に、typescirptを使う環境を作成します。
公式のこちらに書いてあるコマンドでインストールします。

typescriptを使えるようにします。

yarn add @nuxt/typescript-build @nuxt/types

Nuxt Property Decoratorを入れて、デコレータを書けるようにしておきます。

yarn add nuxt-property-decorator

axiosを導入して、nuxtからapiにアクセスできるようにします。

yarn add @nuxtjs/axios

Cros Originエラーへの対応

今回はこのように定義してみました。

proxy: {
  '/api': {
    target: 'http://localhost:8090',
    changeOrigin: true
  },
  '/sanctum': {
    target: 'http://localhost:8090',
    changeOrigin: true
  }
},

ユーザー登録画面のサンプル

ユーザー登録画面のサンプルコードと解説を載せています。

コード

<template>
  <div class="d-flex justify-center">
    <v-form class="col-8">
      <v-text-field label="名前" v-model="name"></v-text-field>
      <v-text-field label="メールアドレス" v-model="email"></v-text-field>
      <v-text-field label="パスワード" v-model="password"></v-text-field>
      <v-text-field label="パスワード確認" v-model="password_confirm"></v-text-field>
      <div class="d-flex justify-center">
        <v-btn color="primary" large @click="register">登録する</v-btn>
      </div>
    </v-form>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
import apiClient from 'axios';

@Component({
  name: 'UserAddPage',
})
export default class UserAddPage extends Vue {
  name: any = '';
  email: any = '';
  password: any = '';
  password_confirm: any = '';

  private async register() {
    const params = {
      name: this.name,
      email: this.email,
      password: this.password,
      password_confirm: this.password_confirm
    }

    apiClient.defaults.withCredentials = true;
    await apiClient.get('/sanctum/csrf-cookie').then(async (response) => {
      await apiClient.post('/api/register', params)
        .then((response: any) => {
          if (response.status == 200) {
            this.$nuxt.$router.push({ path:'board/add' });
          }
        })
        .catch((error: any) => {
          console.log(error);
        });
    });

  }
}
</script>

解説

ユーザー登録のフォームを用意して、上記のように処理を書いてみました。

typescriptで処理している箇所は<script lang="ts">〜</script>の間になります。
registerメソッドを用意していて、登録ボタンが押された場合はこちらのメソッドが動きます。

paramsには画面で入力した値が入ります。これはaxiosでのリクエストで送るためのパラメータです。
次に下記の設定が必要になります。Cookieを送信するかの設定のようです。

 apiClient.defaults.withCredentials = true;

そして通信に入ります。
まず、http://localhost:8090/sanctum/csrf-cookieにアクセスします。
これでcsrf保護の初期化をしておかないと、POST通信で419エラーになるようです。

await apiClient.get('/sanctum/csrf-cookie').then(async (response) => {

csrfの初期化が終わった後に、ユーザー登録APIにリクエストしています。

await apiClient.post('/api/register', params)

その後に、リクエストがステータス200(OK)だったら、掲示板投稿画面に遷移するという流れです。
エラーだったらコンソールログを出力してます。

ログイン画面のサンプル

ログイン画面のサンプルコードと解説を載せています。

コード

<template>
  <div class="d-flex justify-center">
    <v-form class="col-8">
      <v-text-field label="メールアドレス" v-model="email" ></v-text-field>
      <v-text-field label="パスワード" type="password" v-model="password" ></v-text-field>
      <div class="d-flex justify-center">
        <v-btn color="primary" large @click="signIn">サインイン</v-btn>
        <v-btn color="success" large @click="moveCreateAccount" class="ml-2">アカウント作成</v-btn>
      </div>
    </v-form>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
import apiClient from 'axios';

@Component({
  name: 'TopPage',
})
export default class TopPage extends Vue {
  email: any = '';
  password: any = '';

  private async signIn() {
    const params = {
      email: this.email,
      password: this.password,
    }

    apiClient.defaults.withCredentials = true;
    await apiClient.get('/sanctum/csrf-cookie').then(async () => {
      await apiClient.post('/api/login', params)
        .then((response: any) => {
          if (response.status == 200) {
            this.$nuxt.$router.push({ path: 'board/add'});
          }
        })
        .catch((error: any) => {
          console.log(error);
        });
    });
  }

  private moveCreateAccount() {
    this.$nuxt.$router.push({ path: 'user/add'});
  }
}
</script>

解説

ログイン画面を作成して、上記のように処理を書いてみました。
signInメソッドを用意していて、サインインボタンが押された場合はこちらのメソッドが動きます。

signInメソッドの実装ですが、paramsはログインAPIに渡すためのパラメータです。
ユーザー登録の時と同じように、csrfを初期化した後に、ログインAPIにアクセスしています。

ログインできた場合はステータス200が返ってくるので、その後に掲示板投稿画面に遷移しています。
moveCreateAccountメソッドについては、ユーザー登録画面への遷移をしています。

動作確認

バックエンドのルート確認

laravelで定義した、apiのルーティングはこうなりました。

/registerがユーザー登録APIになり、/loginがログインAPIのルートになります。
/board/createが認証した後に、掲示板を登録する箇所です。

Route::middleware('auth:sanctum')->group(function(){
    Route::get('/user', function(Request $request){
        return $request->user();
    });

    Route::post('/board/create', [BoardController::class, 'create']);
});

// ユーザー登録
Route::post('/register', [RegisterController::class, 'register']);

// ログイン
Route::post('/login', [LoginController::class, 'login']);

それぞれにアクセスして、動作確認してみます。

画面からアクセスしてみる

まずユーザー登録をします。

登録して、データベースを確認してみると、このように登録されていることが確認できます。

登録されたユーザーでログインしてみます。

ログインした後に、掲示板の内容を登録してみます。

認証が必要なエリアでも、画面から登録できることが確認できました。

OK.

終わりに

ユーザー登録をして、ログインして認証エリアでの投稿できることが確認できました。

ざっくりとコードと解説を載せてみましたが、なんとなく雰囲気がわかったと思います。
同じようなAPIの処理は別のファイルに書くなどの整理が必要そうです。

適宜コードを修正していく予定ですが、今回のコードは下記にプッシュしています。
https://github.com/YasuakiHirano/codelike_bbs/commits/master

コメント

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