LoginSignup
1
1

More than 3 years have passed since last update.

Laravelの認証(JWT)

Last updated at Posted at 2020-07-28

目次

Laravelの記事一覧は下記
PHPフレームワークLaravelの使い方

Laravelバージョン

動作確認はLaravel Framework 7.19.1で行っています

前提条件

eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています

Laravelでデータベースを扱う準備をする
Laravelでテーブル作成
Laravelで初期データ投入
Laravelでデータベースを操作する(Eloquent編)
本記事は上記ので作成したデータベースとレコード、PHPファイルを使用します

認証に必要なソース生成

コマンドラインで
cd sample
composer require tymon/jwt-auth
xdebugの設定をしているとeclipseが実行していいですかというプロンプトを出すのでOKを押します

コマンドラインで

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

eclipseプロジェクトを右クリック→リフレッシュ
/sample/config/jwt.phpが現れます

コマンドラインで
php artisan jwt:secret
eclipseプロジェクトを右クリック→リフレッシュ
/sample/.envにJWT_SECRETが記載されます

Model修正

/sample/app/Models/User.php修正
(1) use文追記
use Tymon\JWTAuth\Contracts\JWTSubject;追記
(2) implementsにJWTSubject追加
class User extends Authenticatable implements MustVerifyEmail , JWTSubject
(3) メソッド追加
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return [];
}

auth.php修正

/sample/config/auth.php修正
guards->apiを修正

auth.php
‥‥
    'guards' => [
        ‥‥
        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
        ],
    ],
‥‥

Controller

(1) AuthController作成
コマンドラインで
cd sample
php artisan make:controller AuthController
xdebugの設定をしているとeclipseが実行していいですかというプロンプトを出すのでOKを押します
eclipseプロジェクトを右クリック→リフレッシュ
/sample/app/Http/Controllers/AuthController.phpが現れます
/sample/app/Http/Controllers/AuthController.phpを下記に修正します

AuthController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class AuthController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login']]);
    }

    public function login()
    {
        $credentials = request(['email', 'password']);

        if (! $token = auth('api')->attempt($credentials)) {
            return response()->json(['error' => 'メールアドレス、またはパスワードが間違っています'], 401);
        }

        return $this->respondWithToken($token);
    }

    public function me()
    {
        return response()->json(auth('api')->user());
    }

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

        return response()->json(['message' => 'Successfully logged out']);
    }

    public function refresh()
    {
        return $this->respondWithToken(auth('api')->refresh());
    }

    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60
        ]);
    }
}

jwt-authの公式ドキュメントとほとんど同じですが、違っている箇所があります。
auth()関数に引数'api'を渡しています
jwt-authの公式ドキュメントではauth.phpのdefaultsのguardをapiにしているので、auth()に引数を渡さなくてもjwtのguardが取れますが、今回はdefaultsのguardはwebのままにしますので、auth()関数に引数'api'を渡すようにします
また、コンストラクタでmiddlewareを指定しています。middlewareは/sample/routes/web.phpや/sample/routes/api.phpの中でRoute::getやRoute::postの戻り値に対して指定することもできますが、コンストラクタで指定することもできます。この場合$this->middleware('auth:api', ['except' => ['login']]);なので、loginメソッドを除いて、メソッドにリクエストが来るとguard->apiの認証が必要になります

(2) SampleController.php修正
/sample/app/Http/Controllers/SampleController.php修正
api1メソッド、api2メソッド追加

SampleController.php
    public function api1()
    {
        return view('sample.api');
    }

    public function api2(Request $request)
    {
        $data = [
            'a' => 'a_value',
            'b' => 'b_value',
            'c' => $request->input('c')
        ];
        return $data;
    }

(3) /sample/routes/api.php修正
下記を追記

api.php
    Route::post('auth/login', 'AuthController@login');
    Route::post('auth/logout', 'AuthController@logout');
    Route::post('auth/refresh', 'AuthController@refresh');
    Route::post('auth/me', 'AuthController@me');
    Route::post('sample/api2', 'SampleController@api2')->middleware('auth:api');

/sample/routes/api.phpにルーティングを書いた場合、app/Providers/RouteServiceProvider.php#mapApiRoutesによって自動的に/apiがURLの先頭につきます
AuthControllerの各メソッドはAuthControllerのコンストラクタ内で認証の要、不要が設定されていますが、SampleControllerのapi2はここで認証が必要なようにmiddlewareを付けました

(4) /sample/routes/web.php修正
下記を追記
Route::get('sample/api1', 'SampleController@api1');

要ログインURLへ未認証ユーザーがアクセスした場合のエラーメッセージ修正

/sample/app/Http/Middleware/Authenticate.php修正
unauthenticatedメソッド追加

    protected function unauthenticated($request, array $guards)
    {
        throw new AuthenticationException(
            'ログインしてください', $guards, $this->redirectTo($request)
            );
    }

view作成

/sample/resources/views/sample/api.blade.php

api.blade.php
<html>
    <head>
        <title>sample</title>
        <script type="text/javascript">

            function login(){

                var form = document.getElementById("sampleForm1");

                var reqData = {"email": null, "password": null};
                reqData.email = form.email.value;
                reqData.password = form.password.value;

                var req = new XMLHttpRequest();
                req.open(form.method, form.action);
                req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
                req.responseType = 'json';
                req.send(JSON.stringify(reqData));
                req.onload = function () {
                    var json = req.response;
                    if (json['error']) {
                        alert("error:" + json['error']);
                    } else {
                        localStorage.setItem('access_token', json['access_token']);
                        alert('ログイン');
                    }
                }
            }
            function ajax(){

                var form = document.getElementById("sampleForm2");

                var reqData = {"c": null};
                reqData.c = form.c.value;

                var req = new XMLHttpRequest();
                req.open(form.method, form.action);
                req.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('access_token'));
                req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                req.setRequestHeader('Accept', 'application/json');
                req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
                req.responseType = 'json';
                req.send(JSON.stringify(reqData));
                req.onload = function () {
                    var json = req.response;
                    if (json['message']) {
                        alert("message:" + json['message']);
                    } else {
                        alert("a:" + json['a']  + "\n" + "b:" + json['b']+ "\n" + "c:" + json['c']);
                    }
                }
            }
            function logout(){

                var form = document.getElementById("sampleForm3");

                var req = new XMLHttpRequest();
                req.open(form.method, form.action);
                req.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('access_token'));
                req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                req.setRequestHeader('Accept', 'application/json');
                req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
                req.responseType = 'json';
                req.send();
                req.onload = function () {
                    var json = req.response;
                    alert("message:" + json['message']);
                }
            }
        </script>
    </head>
    <body>

        <form id="sampleForm1" action="{{ url('api/auth/login') }}" method="post"  onsubmit="login(); return false;" style="border: #000000 solid 1px; padding: 10px;">
            <div>email:<input type="text" name="email" ></div>
            <div>password:<input type="password" name="password" ></div>
            <input type="submit" value="ログイン">
        </form>

        <br>
        <br>

        <form id="sampleForm2" action="{{ url('api/sample/api2') }}" method="post"  onsubmit="ajax(); return false;" style="border: #000000 solid 1px; padding: 10px;">
            <input type="text" name="c" >
            <input type="submit" value="要認証リクエスト">
        </form>

        <br>
        <br>

        <form id="sampleForm3" action="{{ url('api/auth/logout') }}" method="post"  onsubmit="logout(); return false;" style="border: #000000 solid 1px; padding: 10px;">
            <input type="submit" value="ログアウト">
        </form>

    </body>
</html>

動作確認

http://localhost/laravelSample/sample/api1
a.png
・要認証リクエストの左にあるテキストフィールドに何か入力し、要認証リクエストボタンをクリックします
ログインしてくださいとalertがでました
・メールアドレスとパスワードを入力してログインボタンをクリックします
ログインできました
・要認証リクエストの左にあるテキストフィールドに何か入力し、要認証リクエストボタンをクリックします
SampleController.php#api2のレスポンスが表示されました
・ログアウトボタンをクリックします
ログアウトしました

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