前回まででログイン・ログアウト処理が実装できたので、今回はユーザー登録処理を実装していきます。
ユーザー登録処理の実装
ユーザー登録ページの作成
pagesディレクトリにregister.vueという名前でファイルを作り、適当にユーザー登録用のフォームを作ります。こんな感じに作ってみました。 29行目の様にregisterに必要情報をpostするだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<template> <form @submit.prevent="register"> <v-text-field type="text" name="name" id="name" v-model="form.name" /> <v-text-field type="text" name="email" id="email" v-model="form.email" /> <v-text-field type="password" name="password" id="password" v-model="form.password" /> <v-text-field type="password" name="password_confirmation" id="password_confirmation" v-model="form.password_confirmation" /> <v-btn type="submit">登録</v-btn> </form> </template> <script> export default { data() { return { form: { name: "", email: "", password: "", password_confirmation: "", }, }; }, methods: { async register() { try { await this.$axios.post("register", this.form); } catch (e) {} }, }, }; </script> |
見た目はこんな感じになります。(ラベルぐらい設定しておけば良かった)
config/cors.phpのpathsに'register'を追加します。
テスト実行
このままregisterを試してみます。するとregisterメソッドで「CSRF token mismatch.」とエラーが返ってきます。Laravel Sanctumを導入したことでregister APIの実行時にもCSRF保護をしてくれるようになっている訳ですが、CSRF tokenを持っていないのでエラーが発生しています。
CSRF保護対策
以下によると/sanctum/csrf-cookieにGETリクエストを投げる必要があり、その後はaxiosが自動でやってくれるらしいのでそのように修正します。
SPAを認証するには、SPAの「ログイン」ページで最初に/sanctum/csrf-cookieエンドポイントにリクエストを送信して、アプリケーションのCSRF保護を初期化する必要があります。
https://readouble.com/laravel/8.x/ja/sanctum.html#csrf-protection
具体的には以下コードの様に29行目を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<template> <form @submit.prevent="register"> <v-text-field type="text" name="name" id="name" v-model="form.name" /> <v-text-field type="text" name="email" id="email" v-model="form.email" /> <v-text-field type="password" name="password" id="password" v-model="form.password" /> <v-text-field type="password" name="password_confirmation" id="password_confirmation" v-model="form.password_confirmation" /> <v-btn type="submit">登録</v-btn> </form> </template> <script> export default { data() { return { form: { name: "", email: "", password: "", password_confirmation: "", }, }; }, methods: { async register() { try { await this.$axios.get("sanctum/csrf-cookie"); await this.$axios.post("register", this.form); } catch (e) {} }, }, }; </script> |
余談ですがnuxt.config.jsでaxiosの設定にcredentialsの設定が漏れていて、この処理が動かずハマりました。
認証済みのリダイレクト対策
registerするとLaravel側ではログインしたことになるようなのですが、Nuxt.js側ではまだログイン処理していないのでregister直後にそのままloginも実行するようにします。
具体的には以下コードの様に31-33行目を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<template> <form @submit.prevent="register"> <v-text-field type="text" name="name" id="name" v-model="form.name" /> <v-text-field type="text" name="email" id="email" v-model="form.email" /> <v-text-field type="password" name="password" id="password" v-model="form.password" /> <v-text-field type="password" name="password_confirmation" id="password_confirmation" v-model="form.password_confirmation" /> <v-btn type="submit">登録</v-btn> </form> </template> <script> export default { data() { return { form: { name: "", email: "", password: "", password_confirmation: "", }, }; }, methods: { async register() { try { await this.$axios.get("sanctum/csrf-cookie"); await this.$axios.post("register", this.form); await this.$auth.loginWith("laravelSanctum", { data: { email: this.form.email, password: this.form.password }, }); } catch (e) {} }, }, }; </script> |
この状態で登録処理を実行するとloginメソッドから/homeにリダイレクトされてしまいます。
app\Http\Middleware\RedirectIfAuthenticated.phpの中でクライアントが認証済みの場合はRouteServiceProvider::HOMEへリダイレクトするように書かれているせいなのですが、ちょっと困るので適当にユーザー情報でも返すことにしておきます。
具体的には以下コードの様に27-29行目を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php namespace App\Http\Middleware; use App\Providers\RouteServiceProvider; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class RedirectIfAuthenticated { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null ...$guards * @return mixed */ public function handle(Request $request, Closure $next, ...$guards) { $guards = empty($guards) ? [null] : $guards; foreach ($guards as $guard) { if (Auth::guard($guard)->check()) { // return redirect(RouteServiceProvider::HOME); if ($request->expectsJson()) { return response()->json(Auth::user(), 200); } } } return $next($request); } } |
最後に
ユーザー登録した直後にログインしてしまう仕様は普通なのかな?とちょっと疑問に思いました。あんまり込み入ったことはしたくないのでそれ前提で作っていこうと思います。 次回はメール認証機能を実装してみようと思います。