内容
以下の順番にまとめます。
1. MacへのXAMPP+Laravelインストール
2. ユーザログイン機能の追加
[3. MVCとルーティングの説明]
(https://qiita.com/sonrisa/items/809adf872e6fb3657f81)
[4. ユーザリストの表示]
(https://qiita.com/sonrisa/items/929486929ed8d851a24e)
[5. ユーザリストのペジネーション表示]
(https://qiita.com/sonrisa/items/86efb8caebe207ab8fa8)
6. ユーザ管理APIの追加
7. Vue.jsとAPIベースのユーザ管理アプリの追加準備
8. Vue.jsとAPIベースのユーザ管理アプリの追加
[9. Vue.jsとAPIベースのユーザ管理アプリへのペジネーション追加]
(https://qiita.com/sonrisa/items/d58c56b638924d8c6810)
[10. APIへのJWTAuth認証の追加]
(https://qiita.com/sonrisa/items/97c1f3e8491f76dc2ce2) ←いまここ
11. Vue.jsとAPIベースのユーザ管理アプリへの認証の追加
10. APIへのJWTAuth認証の追加
home2へのアクセス時にログインを求められますが、APIには認証の実装がなされておらずAPIアクセスは誰でもできてしまいますので、このままでは問題です。そのため、home2へのアクセスは誰でもできるようにし、APIアクセスにJWTAuthを使って認証の機能を実装します。その後、次ページでVue.jsで実装されたSPA画面上でログインを実装することとします。
10.1 URI「home2」の認証を削除
認証はルーティング部分で設定していますので、「routes/web.php」を編集し、home2に認証なしでアクセスできるようにします。
...(略)
//Route::middleware('auth')->get('/home2', function () {
// return view('home2');
//})->name('home2');
Route::get('/home2', function () {
return view('home2');
});
「php artisan serve」を実行して、「http://localhost:8000/home2 」にアクセスし、ログアウトしてもアクセスできることを確認します。
10.2 APIへのJWTAuth認証の追加
1. JWTAuthのインストール
Composerコマンドを実行してJWTAuthをインストールします。
$ composer require tymon/jwt-auth
Using version ^0.5.12 for tymon/jwt-auth
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
- Installing symfony/polyfill-util (v1.8.0): Loading from cache
- Installing symfony/polyfill-php56 (v1.8.0): Loading from cache
- Installing namshi/jose (7.2.3): Loading from cache
- Installing tymon/jwt-auth (0.5.12): Loading from cache
namshi/jose suggests installing phpseclib/phpseclib (Allows to use Phpseclib as crypto engine, use version ^2.0.)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
2. 「config/app.php」への設定
下記の通り、JWTAuthのprovidersとaliasesを設定します。
... 中略
'providers' => [
... 中略
Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
],
... 中略
'aliases' => [
... 中略
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
],
];
3. 「app/Http/Kernel.php」への設定
下記の通り、ルーティングでJWTAuthが使えるように設定します。
... 中略
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class, // 追加
'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class, // 追加
];
}
4. JWTAuthの設定ファイル作成
以下のコマンドを実行して「config/jwt.php」ファイルを作成します。
$ php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
Copied File [/vendor/tymon/jwt-auth/src/config/config.php] To [/config/jwt.php]
Publishing complete.
5. 秘密鍵の作成
以下のコマンドを実行して秘密鍵の生成を試みます。
$ php artisan jwt:generate
ReflectionException : Method Tymon\JWTAuth\Commands\JWTGenerateCommand::handle() does not exist
at /Users/Retina/userauth/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:135
131| $callback = explode('::', $callback);
132| }
133|
134| return is_array($callback)
> 135| ? new ReflectionMethod($callback[0], $callback[1])
136| : new ReflectionFunction($callback);
137| }
138|
139| /**
Exception trace:
1 ReflectionMethod::__construct(Object(Tymon\JWTAuth\Commands\JWTGenerateCommand), "handle")
/Users/Retina/userauth/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:135
2 Illuminate\Container\BoundMethod::getCallReflector()
/Users/Retina/userauth/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:115
Please use the argument -v to see more details.
「JWTGenerateCommand.php」にhandle関数がないためエラーが発生しますので、以下の通りhandle関数を追加します。
... 中略
public function handle() {
$this->fire();
}
}
再度秘密鍵の生成を試みます。
$ php artisan jwt:generate
jwt-auth secret [thQFW5fwIfpQiHSKkZfjblb0A9TP8dUP] set successfully
「config/jwt.php」ファイルに秘密鍵の設定が追加されていることを確認します。
$ grep secret config/jwt.php
'secret' => env('JWT_SECRET', 'thQFW5fwIfpQiHSKkZfjblb0A9TP8dUP'),
6. 認証関連のAPIの実装
ここまでに「UserController.php」で定義されたAPIはルーティング「routes/api.php」での定義も含め、全く認証の設定がなされていませんでした。そのため、以下の3点の設定を行います。
- 認証キー発行のAPI実装(これは認証なしでアクセス可能)
- ログインしているユーザの情報を返すAPI実装(要認証)
- 既存ユーザー情報管理APIは認証がないとアクセスができないよう設定
これらは、「UserController.php」へのAPI実装と「routes/api.php」へのルーティング設定で行います。
1) 「UserController.php」へのAPI実装
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class UserController extends Controller
{
... 中略
public function authenticate(Request $request) // emailとpasswordでアクセストークンを取得して返します
{
$credentials = $request->only('email', 'password');
try {
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
return response()->json(['error' => 'could_not_create_token'], 500);
}
$user = User::where('email', $request->email)->first();
return response()->json(compact('user', 'token'));
}
public function getCurrentUser() // トークンに紐づくユーザ情報を取得して返します
{
$user = JWTAuth::parseToken()->authenticate();
return response()->json(compact('user'));
}
}
これにより、「1) 認証キー発行のAPI実装(これは認証なしでアクセス可能)」と「2) ログインしているユーザの情報を返すAPI実装(認証なし)」が実装されます。次にルーティングと認証の設定を追加します。
2) 「routes/api.php」へのルーティング設定
... 中略
Route::post('authenticate','UserController@authenticate');
Route::group(['middleware' => 'jwt.auth'], function () {
Route::resource('users', 'UserController');
Route::get('me', 'UserController@getCurrentUser');
});
これにより、「認証キー発行のAPI」と「既存ユーザー情報管理API」に認証が必要となり、ルーティングの設定が完了します。
7. JWTAuth認証のテスト
例のごとく、「php artisan serve」を実行して、APIのテストを行います。
1) アクセストークンの取得
$ curl -X POST localhost:8000/api/authenticate -d 'email=test1@test.com' -d 'password=(uhBnji9' | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 433 0 395 100 38 2392 230 --:--:-- --:--:-- --:--:-- 2393
{
"user": {
"id": 1,
"name": "test1",
"email": "test1@test.com",
"created_at": "2018-07-18 21:41:12",
"updated_at": "2018-07-18 21:41:12"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODAwMC9hcGkvYXV0aGVudGljYXRlIiwiaWF0IjoxNTMxOTg4ODg5LCJleHAiOjE1MzE5OTI0ODksIm5iZiI6MTUzMTk4ODg4OSwianRpIjoiYm5FQlBXNVBSanBEZ0FrYSJ9.Q9ytQ-sLFsg92d5GcPytIKlFJuVA55vQBaAo1LqayNo"
}
ここでいう、"token"の値がアクセストークンになります。
2) APIの実行
アクセストークンなしでAPIを実行すると「token_not_provided」と言われエラーになります。
$ curl -X GET localhost:8000/api/users | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 30 0 30 0 0 413 0 --:--:-- --:--:-- --:--:-- 416
{
"error": "token_not_provided"
}
取得したアクセストークンをセットしてAPIを実行するとうまくいきます。
以下、ユーザー情報取得するAPIの実行です。
$ curl -X GET localhost:8000/api/users -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODAwMC9hcGkvYXV0aGVudGljYXRlIiwiaWF0IjoxNTMxOTg4ODg5LCJleHAiOjE1MzE5OTI0ODksIm5iZiI6MTUzMTk4ODg4OSwianRpIjoiYm5FQlBXNVBSanBEZ0FrYSJ9.Q9ytQ-sLFsg92d5GcPytIKlFJuVA55vQBaAo1LqayNo'| jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 449 0 449 0 0 1915 0 --:--:-- --:--:-- --:--:-- 1910
{
"current_page": 1,
"data": [
{
"id": 1,
"name": "test1",
"email": "test1@test.com",
"created_at": "2018-07-18 21:41:12",
"updated_at": "2018-07-18 21:41:12"
}
],
"first_page_url": "http://localhost:8000/api/users?page=1",
"from": 1,
"last_page": 4,
"last_page_url": "http://localhost:8000/api/users?page=4",
"next_page_url": "http://localhost:8000/api/users?page=2",
"path": "http://localhost:8000/api/users",
"per_page": 1,
"prev_page_url": null,
"to": 1,
"total": 4
}
以下、アクセストークンに対応するユーザ情報を取得するAPIの実行です。
$ curl -X GET localhost:8000/api/me -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODAwMC9hcGkvYXV0aGVudGljYXRlIiwiaWF0IjoxNTMxOTg4ODg5LCJleHAiOjE1MzE5OTI0ODksIm5iZiI6MTUzMTk4ODg4OSwianRpIjoiYm5FQlBXNVBSanBEZ0FrYSJ9.Q9ytQ-sLFsg92d5GcPytIKlFJuVA55vQBaAo1LqayNo'| jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 127 0 127 0 0 440 0 --:--:-- --:--:-- --:--:-- 440
{
"user": {
"id": 1,
"name": "test1",
"email": "test1@test.com",
"created_at": "2018-07-18 21:41:12",
"updated_at": "2018-07-18 21:41:12"
}
}
以上、「10. APIへのJWTAuth認証の追加」の完了です。
次は、「11. Vue.jsとAPIベースのユーザ管理アプリへの認証の追加」です。
参考URL
参考1. JWTAuthのインストール方法 http://jwt-auth.readthedocs.io/en/develop/laravel-installation/#add-service-provider-laravel-54-or-below
参考2. 秘密鍵生成「php artisan jwt:generate」が失敗しないようにするためのJWTGenerateCommand.phpの編集 https://laracasts.com/discuss/channels/laravel/class-tymonjwtauthprovidersjwtauthserviceprovider-not-found-1