LoginSignup
10
11

More than 5 years have passed since last update.

モダンな技術を全く知らないSIer5年目がWebサービスを作ることになったため0から勉強する ~Laravel jwt-auth編~

Last updated at Posted at 2019-04-27

はじめに

現在SIer5年目でjavascript(Jqueryのみ)、PHP(フレームワーク無し)を2年ほど、C#(Windowsアプリ)3年ほどやってきました。
色々なご縁があり、個人で最近Webサービスの立ち上げをやることになったのですが何せ本当にWebサービスを立ち上げるための知識がほぼ0に等しいです:sob:

ただ今後のキャリアを考えた時に今のままではいけないと思いチャレンジすることにしました。

まずは最初に技術を習得しないといけないので、学ぶ&アウトプットするために毎回投稿していこうと思います。
今後身についていこうと思ってるのは下記のような技術です。
AWS
Docker
CI/CD環境の構築
Laravel
Nuxt.js
今回はLaravel+Nuxtについて学んでいきます。

今回学ぶこと

Laravel+Nuxtでのログイン機能を作成していこうかと思います。
jwt-authを使用してログインを実現してきます。

参考サイト

jwt-auth公式サイト

前提

Laravel 5.8
Nuxt 2.5.4
jwt-auth

このチュートリアルで勉強してみました
Laravel + NuxtJS authentication

Laravel + NuxtJS認証:プロジェクトの設定

まずはLaravel、Nuxtのプロジェクト設定を行う

認証機能を追加する

php artisan make:auth

/app/ModelsにUser.phpを移動する

mkdir ./app/Models
mv ./app/User.php ./app/Models

参照しているファイルのパスを修正する'

/app/Models/User.php
- namespace App\;
+ namespace App\Models;
/app/Http/Controllers/Auth/RegisterController.php
- use App\User;
+ use App\Models\User;
/config/auth.php
- 'model' => App\User::class,
+ 'model' => App\Models\User::class,
/config/services.php
- 'model' => App\User::class,
+ 'model' => App\Models\User::class,

マイグレーションの実行

php artisan migrate

composerでjws-authをインストールする

まずはインストールをする

 composer require tymon/jwt-auth dev-develop

次のコマンドを実行してパッケージ設定ファイルを公開します。

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

秘密鍵を作成する

php artisan jwt:secret

注意

Laravelのバージョンによって必要な手順が異なるため
公式サイトを確認する

jwt-authのトークン発行を有効にする

JWT用の関数を追加する

/app/Models/User.php
- class User extends Authenticatable
+ class User extends Authenticatable implements JWTSubject
/app/Models/User.php
public function getJWTIdentifier()
{
    return $this->getKey();
}

public function getJWTCustomClaims()
{
    return [];
}

認証ガードを設定する

/config/auth.php
'defaults' => [
    'guard' => 'api',
    'passwords' => 'users',
],

...

'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

LaravelのAPIを定義する

LaravelでAPIのルーティングを設定していく

/routes/api.php
<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::group(['prefix' => '/auth', ['middleware' => 'throttle:20,5']], function (){
   Route::post('/register', 'Auth\RegisterController@register');
   Route::post('/login', 'Auth\LoginController@login');
});

Route::group(['middleware' => 'auth:api'], function (){
    Route::get('/me', 'MeController@index');
    Route::get('/auth/logout', 'MeController@logout');
});

各APIを実装していく

ユーザ登録APIのコントローラを実装する

※本来はPasswordは2回入力してもらうためにValidationはconfirmationも入れるべきですが今回が簡単に実装するために省略します。

App/Http/Controllers/Auth/RegisterController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Tymon\JWTAuth\JWTAuth;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.

    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = '';

    protected $auth;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct(JWTAuth $auth)
    {
        $this->auth = $auth;
    }

    /**
     * Handle a registration request for the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     * 登録関数をオーバライドする
     */
    public function register(Request $request)
    {
        $validator = $this->validator($request->all());
        if(!$validator->fails()){
            $user = $this->create($request->all());

            $token = $this->auth->attempt($request->only(`email`, 'password'));

            return response()->json([
                'success' => true,
                'data' => $user,
                'token' => $token
            ], 200);
        }

        return response()->json([
            'success' => false,
            'errors' => $validator->errors()
        ], 422);
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\Models\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
}

ログインAPIのコントローラを実装する

/app/Http/Controllers/Auth/LoginController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\JWTAuth;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '';

    protected $auth;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct(JWTAuth $auth)
    {
        $this->auth = $auth;
    }

    /**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function login(Request $request)
    {

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if ($this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return response()->json([
                'success' => false,
                'errors' => [
                    "You ve been locked out"
                ]
            ]);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        try{
            if(!$token = $this->auth->attempt($request->only('email', 'password'))){
                return response()->json([
                    'success' => false,
                    'errors' => [
                        'email' => [
                            "Invalid email address or password"
                        ]
                    ]
                ], 422);
            }
        } catch (JWTException $e){
            return response()->json([
                'success' => false,
                'errors' => [
                    'email' => [
                        "Invalid email address or password"
                    ]
                ]
            ], 422);
        }

        return response()->json([
            'success' => true,
            'data' => $request->user(),
            'token' => $token
        ], 200);



    }
}

ユーザ情報取得APIとログアウトAPIのコントローラを実装する

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

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Tymon\JWTAuth\JWTAuth;

class MeController extends Controller
{
    protected $auth;

    public function __construct(JWTAuth $auth)
    {
        $this->auth = $auth;
    }

    public function index(Request $request){
        return response()->json([
            'success' => true,
            'data' => $request->user()
        ]);
    }

    public function logout()
    {
        auth()->logout();

        return response()->json([
            'success' => true,
        ]);
    }
}

CORSの設定

CORSについてはここがわかりやすかったので見てみてください

Laravelではlaravel-corsという便利なモジュールがあるので今回はこれを使用します。
※本来は信頼できるドメインのみアクセス可能にするべきだが今回は全部のアクセスを許可するようにする

composer require barryvdh/laravel-cors

app/Http/Kernel.php
    protected $middlewareGroups = [
        ...

        'api' => [
            'throttle:60,1',
            'bindings',
            \Barryvdh\Cors\HandleCors::class,
        ],
    ];

補足

実装の動画と多少変更してる箇所もあります。(ディレクトリ構成も変えてますが好みかなと思います)
例えば、api.phpの認可するためのmiddlewarejwt.authにしてますが
現在のjwt-authのドキュメントは、auth.phpのguardsの設定を変更して
middlewareapi:authにしてます。

正直どちらが正しいかはわからなかったのでもしわかる方は教えていただけると幸いです。

10
11
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
10
11