LoginSignup
1
0

More than 1 year has passed since last update.

Laravel 8 Sanctum認証で安全なRest APIを作成

Last updated at Posted at 2021-12-17
1 / 2

初めての記事ですが、軽くSanctumを使用してAPI作成を紹介していきたいと思います。よろしくお願いします。

●ログイン者のみアクセスできるAPIを作成
●環境:Laravel8

新しいプロジェクトを作成します。

 create project laravel/laravel sanctum_test

.envファイルの設定を自分の環境と合わせて修正します。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=root
DB_PASSWORD=

Sanctumパッケージをインストール

 composer require laravel/sanctum

app/Http/Kernel.phpにapiミドルウェア設定を行います。追加されている場合、コメントアウトを外します。

 修正前:
 protected $middlewareGroups = [
        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
        ],
    ];

修正後:
 protected $middlewareGroups = [
        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
        ],
    ];

マイグレートを実行しデフォルトのユーザモデルにSanctumの設定を追加

 php artisan migrate
 <?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

//Sanctum
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

app\Http\Controllersにログイン処理を作成

 <?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use \Symfony\Component\HttpFoundation\Response;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller{

    public function index(Request $request)
    {
        $email = $request->email;
        $password = $request->password;

        //バリデーション
        $credentials = $this->validator($request);

        if(Auth::attempt($credentials)){
            $user = User::where('email', $email)->first();

            if($user && Hash::check($password, $user->password)){
                //既存トークン削除
                $user->tokens()->delete();

                $user->email_verified_at = new Carbon ('now');
                $user->save();

                $result =  [
                    'token' => $user->createToken("login:user{$user->id}")->plainTextToken
                ];

                return response()->json($result, Response::HTTP_OK);
            }

        }
    }

    /**
      * @param Request $request
      * @return array
      */
    protected function validator(Request $request)
    {
        return $this->validate($request, [
            'email'   => 'required',
            'password' => 'required'
        ]);
    }
}

routes/api.phpにルートを設定

 Route::post('/login', 'App\Http\Controllers\LoginController@index')->name('login');

作成したログインAPIをPostmanでアクセスしてみると!Screen Shot 2021-12-16 at 18.03.27.png
Screen Shot 2021-12-16 at 18.00.58.png

次は上記のトークンでログイン者のみアクセルできるAPIを作成いたします。まず新しいModelを作成

 php artisan make:model Article

Articleテーブル用のダミーデータを作成してArticleFactory.phpに以下を追加

 php artisan make:factory ArticleFactory
 <?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class ArticleFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'title' => $this->faker->sentence,
            'body' => $this->faker->paragraph,
            'category_id' => rand (1,5)

        ];
    }
}

DatabaseSeeder.phpにも追加

 <?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Article;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        Article::factory()->count(20)->create();
    }
}

ダミーデータSeedを実行します。これでデータの準備が終わりました。作成したArticleテーブルのデータを取得するAPIの作成を進みます。

 php artisan db:seed

Article取得APIを作成.「--api」オプションをつけたのでCRUDの関数が揃っている状態ですが、
今回はindex関数のみに使います。

 php artisan make:Controller ArticleApiController --api

ArticleApiControllerに以下の処理を追加

 <?php

namespace App\Http\Controllers;

use App\Models\Article;
use Illuminate\Http\Request;

class ArticleApiController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return Article::all();
    }
}

またルートを設定

 //Sanctum認証
Route::middleware('auth:sanctum')->group(function(){
      Route::get('/articles','App\Http\Controllers\ArticleApiController@index'); 
});

Postmanの認証設定で発行されたトークンを入れてアクセスするとちゃんと返しています。Screen Shot 2021-12-17 at 11.49.41.png

今回違うトークンを使ってみると認証失敗となっています。これで終わりですが、よかったら参考してください。最後まで読んでくれてありがとう!
Screen Shot 2021-12-17 at 11.49.59.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0