LoginSignup
2
1

More than 1 year has passed since last update.

laravel-doctrineで認証

Last updated at Posted at 2021-06-17

はじめに

前回の記事の続きです。今回はlaravel-doctrineを使いつつ、Authファサードで認証を行うところまで行きます。

laravel-doctrineで認証

Userエンティティの更新

まず、Laravelで認証できるようにUserエンティティを更新します。

あるクラスをLaravelで認証できるようにするためには、そのクラスにIlluminate\Contracts\Auth\Authenticatableを実装する必要があります。また、そのクラスをデータベースから取得してくるIlluminate\Contracts\Auth\UserProviderクラスを作る必要があります。

詳しくはこちらのドキュメントをご覧ください。

laravel-doctrineではIlluminate\Contracts\Auth\Authenticatableの実装に必要なメソッドを既に定義したtraitと、そのプロバイダーが用意されているのでこれらを使います。

また、ユーザーを一意に識別するカラムとしてemailを追加しています。

app/Entities/User.php
<?php

namespace App\Entities;

use Doctrine\ORM\Mapping as ORM;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Support\Arrayable;
use LaravelDoctrine\ORM\Auth\Authenticatable as AuthenticatableTrait;

/**
 * @ORM\Entity
 */
class User implements Arrayable, Authenticatable
{
    use AuthenticatableTrait;

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\Column(type="string")
     */
    protected $email;

    public function getName()
    {
        return $this->name;
    }

    public function setName($name): self
    {
        $this->name = $name;
        return $this;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email): self
    {
        $this->email = $email;
        return $this;
    }

    public function toArray()
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
        ];
    }
}

エンティティを更新したら、マイグレーションの作成と適用をします。

sail artisan doctrine:migrations:diff
sail artisan doctrine:migrations:migrate

configの更新

laravel-doctrineが提供しているUseProviderを使うように設定ファイルを更新します。

config/auth.php
...
    'providers' => [
        'users' => [
            'driver' => 'doctrine', // laravel-doctrineが提供しているUserProvider
            'model' => \App\Entities\User::class, // 変更
        ],
...

コントローラーの作成とルートの登録

コントローラーを作成し、login()register()profile()アクションを作成します。
また、今回は認証にCookieを使うので、apiミドルウェアにCookieを使う設定を入れます。

app/Http/kernel.php
    protected $middlewareGroups = [
...
...
        'api' => [
            'throttle:api',
            \Illuminate\Session\Middleware\StartSession::class, // 追加
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];
...
...
routes/api.php
<?php

use App\Http\Controllers\AuthController;
use Illuminate\Support\Facades\Route;

Route::post('login', [AuthController::class, 'login']);
Route::post('register', [AuthController::class, 'register']);
Route::get('profile', [AuthController::class, 'profile']);

app/Http/Request/LoginRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class LoginRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'email' => 'required|string|email',
            'password' => 'required|string',
        ];
    }
}

app/Http/Request/RegisterRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class RegisterRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required|string',
            'email' => 'required|string|email',
            'password' => 'required|string',
        ];
    }
}

login()ではポストパラメータで受け取ったemailpasswordを用いて、認証を行います。
Illuminate\Contracts\Auth\AuthenticatableIlluminate\Contracts\Auth\UserProviderを使用していますので、LaravelのAuthファサードを使って認証を行うことができています。

register()ではポストパラメータで受け取ったデータを使ってUserをDBに登録します。前の記事でやったのと同じようにDBへの永続化はEntityManagerを使って行います。パスワードは平文ではなく、Illuminate\Contracts\Hashing\Hasherを使って暗号化してから保存する必要があります。

profile()では認証済みのUserを取得して、データをレスポンスで返します。こちらもlogin()と同様にAuthファサードを使うことができます。

app/Http/Controllers/AuthController.php
<?php

namespace App\Http\Controllers;

use App\Entities\User;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\RegisterRequest;
use Doctrine\ORM\EntityManagerInterface;
use Illuminate\Contracts\Hashing\Hasher;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
    public function login(LoginRequest $request): JsonResponse
    {
        if (!Auth::attempt($request->validated())) {
            return response()->json([
                'Invalid credential'
            ], 400);
        }

        return response()->json([]);
    }

    public function register(RegisterRequest $request, Hasher $hasher, EntityManagerInterface $entityManager): JsonResponse
    {
        $input = $request->validated();

        $user = new User();
        $user->setName($input['name']);
        $user->setEmail($input['email']);
        $user->setPassword($hasher->make($input['password']));

        $entityManager->persist($user);
        $entityManager->flush();

        return response()->json($user);
    }

    public function profile(): JsonResponse
    {
        $user = Auth::user();
        return response()->json($user);
    }
}

curlで実際に叩くとこのような感じです。

# Userを登録
$ curl http://localhost/api/register -d "name=TARO&email=test@example.com&password=password"
{"id":1,"name":"TARO"}


# 登録したUserでログイン
$ curl -vvv http://localhost/api/login -d "email=test@example.com&password=password"
....
....
< Set-Cookie: laravel_session=vjJ4KExxhGZt0qjtlxcw6w4tL3lsGalm8687V8O3; expires=Thu, 17-Jun-2021 16:20:09 GMT; Max-Age=7200; path=/; httponly; samesite=lax
...
...
[]%

# Cookieなしで叩くとレスポンスデータは空ですが
$ curl http://localhost/api/profile
{}

# Cookieをつけると認証が通ります
$ curl http://localhost/api/profile -b laravel_session=vjJ4KExxhGZt0qjtlxcw6w4tL3lsGalm8687V8O3
{"id":1,"name":"TARO"}

終わりに

laravel-doctrineを使った認証ですが、想像していたよりだいぶ楽でした。UserProviderAuthenticatableの実装が提供されているのが大きかったです。laravelでは色々なinterfaceが定義されており、これらを実装するだけで手軽に連携できるのがいいですね
。改めてinterfaceの重要さを感じました。

2
1
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
2
1