Laravel(Sanctum)とVue(Nuxt)でAPI認証をする方法
いつもご利用ありがとうございます。
この記事には広告が掲載されており、その広告費によって運営しています。
目次
⇨ Laravel 記事の目次はこちら ⇨ Vue 記事の目次はこちら
Laravel(Sanctum)と Nuxt の auth-module を使って、API 認証の実装をしていきます。
はじめに
Sanctum とは?
Laravel8 からリリースされた Laravel の最も簡単な認証系のパッケージです。
以前までは、API の認証パッケージでは LaravelPassport というものがよく使われていましたが、機能過多でした。
しかし、機能過多なので「最初に使うにしては分かりにくい」ということで、
もっとシンプルに API 認証することが Sanctum で可能になりました。
Nuxt-Auth-Module とは?
Nuxt の認証情報を保持するための、標準パッケージです。
Vue の、Auth-module というパッケージを Nuxt で設定しやすいように作られているのがこのパッケージとなります。
当記事は、token を使った実装
その他の方法としては、Cookie やセッションを使った実装がありますが、この記事では token を使った実装となっていますのでご注意ください。
ざっくり流れの説明
①Laravel で認証の token を発行する
②Nuxt-auth で token を保持する
こういう流れになります。
まずは、Laravel 側から設定していきましょう。
Laravel 側の設定
コマンドで必要なものを入れていきます。
プロジェクトの作成
composer create-project laravel/laravel laravel-api
Sanctum のインストール
composer require laravel/sanctum
ローカルサーバーを立てておきます
php artisan serve
ローカルサーバーがたった
Starting Laravel development server: http://127.0.0.1:8000
設定ファイルを変更できるようにする
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
database/migrations に新しいファイルが追加されました。
personal_access_tokens を変更することができます。
データベースの接続の設定は省略
人によって接続の仕方が違うと思うので省略します。
もし、データベースの接続方法が分からない場合は、一番簡単(個人的に)なこちらの記事でやってみてください
Laravel のデータベースの接続方法(MAMP の場合)
token を保存するデータベースの作成
personal_access_tokens テーブルを作成します(前のコマンドで生成されたファイルでテーブルを作るだけです)
コマンド
php artisan migrate
このコマンドで失敗する人は、データベースの接続がうまくいっていません。
パッケージのバージョン
"laravel/framework": "^8.75",
"laravel/sanctum": "^2.14",
App/Http/Kernel.php の変更
42 行目あたりの api の項目で、コメントアウトされている記述のコメントアウトを外します
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
App/Http/Middleware/VerifyCsrfToken.php の変更
protected $except = [
'api/login'
];
ログインのための POST だけは認証していなくても許可をするようにしました。
User モデルで APItoken の認証をします的な設定をする
このような記述があることを確認してください。
多分、コマンドで勝手に記述がされています。
App/Models/User.php
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
//以下略
テストユーザーのデータを作成する
Seeder という機能を使って、ユーザーのテストデータを作っていきます。
Laravel でテストデー タを用意する方法(Seeder の使い方)
コマンドで Seeder ファイルを作成する
php artisan make:seeder UsersTableSeeder
database/seeders/UsersTableSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
//↓3行追記
use Hash;
use DB;
use App\Models\User;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$data = [
[
'name' => 'ララテックくん',
'email' => 'laratech@example.com',
'password' => Hash::make('password')
],
];
DB::table('users')->insert($data);
}
}
上記の Seeder で
email:laratech@example.com
password:password
でログインできるユーザーが作成されます。
database/seeders/DatabaseSeeder.php を編集する
変更が必要な場所のみ
public function run()
{
$this->call(UsersTableSeeder::class);
// \App\Models\User::factory(10)->create();
}
コマンド
今設定したクラスを読み込む
composer dump-autoload
データの生成
php artisan db:seed
Laravel でログイン機能をつける
ログイン用の route の作成
routes/api.php
use App\Http\Controllers\Api\Auth\LoginController;
Route::post('/login',[LoginController::class,'login']);
ログイン用の関数の作成
メールとパスワードの入力がある前提で、
ユーザーをメールで検索 ⇨ そのユーザーの保存されているパスワードと照合する
一番シンプルな関数を書きます。
<?php
namespace App\Http\Controllers\Api\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
//2行追記
use Hash;
use Illuminate\Validation\ValidationException;
class LoginController extends Controller
{
//関数を追記
public function login(Request $request)
{
$email = $request->email;
$password = $request->password;
$user = User::where('email', $email)->first();
// Hash::check(今入力されたパスワード、DBに保存された暗号化済みのパスワード)
if (! $user || ! Hash::check($password, $user->password)) {
//ユーザーがいない|または|DBのパスワードと合致していれば
throw ValidationException::withMessages([
'email' => ['メールが違うか、パスワードが違うか'],
]);
}
$token = $user->createToken('token')->plainTextToken;
//tokenという名前で返す
return response()->json(compact('token'),200);
}
}
Nuxt 側の設定
プロジェクトの作成
yarn create nuxt-app nuxt-api
コマンドでローカルホスト
yarn dev
ローカルホストがたちました
Nuxt @ v2.15.8 │
│ │
│ ▸ Environment: development │
│ ▸ Rendering: server-side │
│ ▸ Target: static │
│ │
│ Listening: http://localhost:3000/
nuxt-axios を入れる
コマンド
yarn add @nuxtjs/axios
nuxt.config.js の modules に追記
modules: ["@nuxtjs/axios"],
axios のベースとなる URL(今回でいえば Laravel のローカルサーバーのアドレス)
nuxt.config.js に追記する
publicRuntimeConfig: {
axios: {
baseURL: process.env.BASE_URL,
},
},
.env ファイルを作成する
Nuxt のプロジェクトディレクトリの直下に.env という名前でファイルを作成してください。
.env に追記する
BASE_URL=http://127.0.0.1:8000
ログインフォームを作る
pages/login/index.vue ファイルを作成する
Vuetify を使っているので、Vuetify 使っていない人は、v-text-field のところを input タグにしてください。
<template>
<v-row>
<v-col class="text-center">
<v-text-field label="email" v-model="email"></v-text-field>
<v-text-field label="password" v-model="password"></v-text-field>
<v-btn @click="login" color="blue" outlined>ログイン</v-btn>
</v-col>
</v-row>
</template>
<script>
export default {
data() {
return {
email: "",
password: "",
}
},
methods: {
login() {
console.log("おした")
this.$axios
.$post("/api/login", {
email: this.email,
password: this.password,
})
.then(response => {
console.log(response)
})
},
},
}
</script>
ログインしてみる
laratech@example.com
password
を入力欄に入れてボタンを押す
コンソールに token が返却されていれば OK
{token: '6|XTSYN6HylafFkHfgWHxoODrrfA3kDjlptQFPChaB'}
以上動作確認でした。
あとは、Nuxt で token をうまく使って、認証機能を作ります
nuxt-auth-module を使う
コマンドでパッケージを入れる
yarn add @nuxtjs/auth-next
nuxt.config.js
modules に追記する。
さきほど axios でも追記しているので、modules の項目が二つにならないように、
以下のようにまとめてください。
modules: ["@nuxtjs/axios", "@nuxtjs/auth-next"],
//Modules: https://auth.nuxtjs.org/schemes/local
auth: {
strategies: {
local: {
token: {
property: "token",
global: true,
// required: true,
// type: 'Bearer'
},
user: {
property: "user",
// autoFetch: true
},
endpoints: {
login: { url: "/api/login", method: "post" },
logout: { url: "/api/logout", method: "post" },
user: { url: "/api/user", method: "get" },
},
},
},
},
ボタンで動かした関数の中身を auth にする
async userLogin() {
try {
let response = await this.$auth.loginWith('local', { data: this.login })
console.log(response)
} catch (err) {
console.log(err)
}
}
Laravel でユーザー情報を返す API を作る
api/user という URL でユーザー情報を返す API を作成します。
api/user という URL にする理由は、Nuxt.config.js のエンドポイントで設定しているからです。
ここの記述のことです。
endpoints: {
login: { url: "/api/login", method: "post" },
logout: { url: "/api/logout", method: "post" },
user: { url: "/api/user", method: "get" },
},
api.php
Route::group(['middleware' => 'auth:sanctum'],function(){
Route::get('/user',[UserController::class,'index']);
});
コマンドでコントローラーを作る
php artisan make:controller Api/UserController
App/Http/Controllers/Api/UserController.php
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
class UserController extends Controller
{
public function index(Request $request)
{
// $user = User::find(1);
$user = $request->user();
return response()->json(compact('user'),200);
}
}
この URL を叩くと今ログインしているユーザーの情報を返すようになりました。
Nuxt 側でユーザー情報を表示する
template 内で使う時
<template>
<div>
<p>{{ $auth.loggedIn }}</p>
<p>{{ $auth.user }}</p>
</div>
</template>
表示
true(認証しているので。認証していない 時はfalse)
{ "id": 1, "name": "ララテックくん", "email": "laratech@example.com", "email_verified_at": null, "created_at": null, "updated_at": null }
script 内で使う時
this をつけるだけです。
<script>
export default {
created(){
console.log(this.$auth.user)
}
}
</script>
ログインしていない人しかできない処理を書く
Laravel 側
.env に設定を書く
パスは、Nuxt のパスを書いてください
.env
SESSION_DOMAIN=http://127.0.0.1:3000
SANCTUM_STATEFUL_DOMAINS=http://127.0.0.1:3000
env を変えたら、コマンド
php artisan config:cache
この内容は config/session.php と、config/sanctum に反映されます。
api.php
post 用の行を追加
Route::group(['middleware' => 'auth:sanctum'],function(){
Route::get('/user',[UserController::class,'index']);
Route::post('/post',[PostController::class,'store']);
});
コントローラーを作る
php artisan make:controller Api/PostController
App/Http/Controller/Api/PostController.php に書く
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function store(Request $request)
{
$content = $request->content;
//$user情報をとりたいときは
$user = $request->user();
// $userId = $request->user()->id;
return response()->json(compact('content','user'),200);
}
}
Nuxt に書く
<template>
<v-btn @click="post">ポスト!</v-btn>
</template>
<script>
export default {
data() {
return {
content: "試しのポスト",
}
},
methods: {
post() {
this.$axios
.$post("/api/post", {
content: this.content,
})
.then(response => {
console.log(response)
})
},
},
}
</script>
結果
content: "試しのポスト",
user: {id: 1, name: 'ララテックくん', email: 'laratech@example.com', ....
以上です。お疲れ様でした!
まとめ
以上です。
全てのコードは以下の GitHub に載せています。
記事に誤りがある際や感想がありましたら、Youtube のコメントで教えていただけると幸いです。
人気記事