Implementation dingo/api & tymon/jwt-auth package
Dingo/API
https://github.com/dingo/api
Install
$ laravel new api_jwt
$ cd api_jwt
$ composer require dingo/api:1.0.x@dev
Config
config/app.php
1 2 3 4 5 6 7 8
| 'providers' => [ Dingo\Api\Provider\LaravelServiceProvider::class ] 'aliases' => [ Dapi => Dingo\Api\Facade\API::class, Droute => Dingo\Api\Facade\Route::class, ]
|
產生config/api.php
$ php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
.ENV or config/api.php
.env
1 2 3 4 5 6 7
| API_STANDARDS_TREE=vnd API_SUBTYPE=myapp API_VERSION=v1 API_PREFIX=api API_DOMAIN=trackye.dev API_NAME=MyAPI API_DEBUG=true
|
Routes
routes/api.php
1 2 3 4 5 6 7
| $api = app('Dingo\Api\Routing\Router'); $api->version('v1', function($api) { $api->get('hello', function() { return "Hello"; }); $api->get('world', 'App\Http\Controllers\ExampleController@index'); });
|
Testing
.env資料庫設定
php artisan migrate
php artisan make:seeder UsersTableSeeder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?php use Illuminate\Database\Seeder; use App\User; use Illuminate\Support\Facades\Hash; class UsersTableSeeder extends Seeder { public function run() { $user1 = new User(); $user1->name = 'A'; $user1->email = 'A@A.A'; $user1->password = Hash::make('A'); $user1->save(); $user2 = new User(); $user2->name = 'B'; $user2->email = 'B@B.B'; $user2->password = Hash::make('B'); $user2->save(); } }
|
php artisan db:seed
php artisan api:routes
http://api_jwt.dev/api/hello
http://api_jwt.dev/api/world
前言:
- API的用戶認證(Authorization)可以使用JWT(內部登入) or OAuth2.0(內部登入or第三方例如facebook)
- Oauth2.0: Laravel5.3有新的Passport package, 所以不再用
lucadegasperi/oauth2-server-laravel
(5.2以前的解決方案)
JWT(Json Web Token)
https://github.com/tymondesigns/jwt-auth
Install
composer require tymon/jwt-auth:0.5.*
Config
config/app.php
1 2 3 4 5 6 7 8
| 'providers' => [ Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class, ] 'aliases' => [ 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class, ]
|
config/api.php
1 2 3
| 'auth' => [ 'jwt' => Dingo\Api\Auth\Provider\JWT::class, ],
|
產生config/jwt.php
$ php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
.ENV or config/jwt.php
php artisan jwt:generate
會自動加到config/jwt.php
or copy to .env
1
| JWT_SECRET=npoW1xxv8yXwwQVWO3GljPO9qBncmuIb
|
Return Token
app/Http/Kernel.php
1 2 3 4
| protected $routeMiddleware = [ 'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class, 'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class, ];
|
假如使用者登入成功, return token
routes/api.php
1
| $api->post('authenticate', 'App\Http\Controller\ExampleController@authenticate');
|
App\Http\Controllers\ExampleController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| use JWTAuth; use Tymon\JWTAuth\Exceptions\JWTException; class ExampleController extends Controller { public function authenticate(Request $request) { $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); } return response()->json(compact('token')); } }
|
Example Testing
POST
api_jwt.dev/api/authenticate
email: A@A.A
Password: A
curl -X POST -H "Content-Type:application/x-www-form-urlencoded" http://api_jwt.dev/api/authenticate -d "email=A@A.A&password=A"
取得token!
Add Middleware 以下都需要token
show users
routes/api.php
1 2 3
| $api->version('v1', ['middleware' => 'api.auth'], function($api){ $api->get('users', 'App\Http\Controllers\ExampleController@index'); });
|
PS: api.auth就是jwt(config/api.php) => jwt.auth, jwt.refresh
1 2 3 4 5
| public function index() { $users = User::all(); return response()->json($users); }
|
加入Header
Authorization: Bearer <token>
curl -H "Authorization: Bearer <token>" http://api_jwt.dev/api/users
要有token才能使用!
show user
routes/api.php
1 2 3
| $api->version('v1', ['middleware' => 'api.auth'], function($api){ $api->get('user', 'App\Http\Controllers\ExampleController@show'); });
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| use Tymon\JWTAuth\Exceptions; public function show() { try { $user = JWTAuth::parseToken()->toUser(); if (! $user) { return response()->json(['error' => 'User not found'], 400); } } catch (TokenInvalidException $e) { return response()->json(['error' => 'Token is invalid'], 401); } catch (TokenExpiredException $e) { return response()->json(['error' => 'Token has expired'], 401); } catch (TokenBlacklistedException $e) { return response()->json(['error' => 'Token is blacklisted'], 401); } return response()->json($user); }
|
curl -H "Authorization: Bearer <token>" http://api_jwt.dev/api/user
會根據token判斷是哪一個user, 非常厲害
refresh token
routes/api.php
1 2 3
| $api->version('v1', ['middleware' => 'api.auth'], function($api){ $api->get('token', 'App\Http\Controllers\ExampleController@getToken'); });
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public function getToken() { $token = JWTAuth::getToken(); if (! $token) { return response()->json(['error' => 'Token is invalid'], 401); } try { $refreshedToken = JWTAuth::refresh($token); } catch (JWTException $e) { return response()->json(['error' => 'Something went wrong'], 400); } return response()->json($refreshedToken); }
|
curl -H "Authorization: Bearer <token>" http://api_jwt.dev/api/token
得到傳進來的token, 返回一個新的token
delete user
routes/api.php
1 2 3
| $api->version('v1', ['middleware' => 'api.auth'], function($api){ $api->delete('delete', 'App\Http\Controllers\ExampleController@destroy'); });
|
1 2 3 4 5 6 7 8
| public function destroy() { $user = JWTAuth::parseToken()->authenticate(); if (! $user) { return response()->json(['error' => 'Fail the delete provess'], 401); } $user->delete(); }
|
curl -X DELETE -H "Authorization: Bearer <token>" http://api_jwt.dev/api/delete
檢查token, 再刪user