🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Dingo API和JWT 参考: https://laravel-china.org/articles/5804/laravel54jwtdingoapi-building-restfulapi ## 引入 Dingo API https://github.com/liyu001989/dingo-api-wiki-zh JWT https://github.com/tymondesigns/jwt-auth/wiki/installation 在composer.json中写 ``` "require": { "php": ">=5.5.9", "laravel/framework": "5.1.*", "dingo/api": "1.0.*@dev", "tymon/jwt-auth": "0.5.*" }, ``` 运行composer update 打开 config/app.php,注册必要的 service provider 在你的应用 providers 之前。 ``` 'providers' => [ Dingo\Api\Provider\LaravelServiceProvider::class ``` 如果你想在配置文件中改变一些配置,你可以使用下面的 Artisan 命令发布配置文件 `php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"` 任何你就可以看到config文件夹下有api.php 接下来配置JWT config/app.php ```php 'providers' => [ Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class, ``` ```php 'aliases' => [ 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class, ``` 然后执行 `php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"` 生成配置文件 然后可以看到config文件夹下面有jwt.php 最后执行 `php artisan jwt:generate` 会生成一个key给我们用 如果用laravel5.5可能遇到个问题 ![](https://box.kancloud.cn/482324b5a1923e96f4db61ceb95bc11b_2368x1371.png) 安装上面来就可以 在.env文件中为dingo api写上配置信息,写4个就可以 ``` API_STANDARDS_TREE=vnd API_PREFIX=api API_VERSION=v1 API_DEBUG=true ``` 在config/api.php中,有auth这个空数组,编辑它 ```php 'auth' => [ 'basic'=>function($app){ return new Dingo\Api\Auth\Provider\Basic($app['auth']); }, 'jwt'=>function($app){ return new Dingo\Api\Auth\Provider\JWT($app['Tymon\JWTAuth\JWTAuth']); } ], ``` 在config/jwt.php文件中,有`'secret' => env---` 这就是我们之前生成的key,里面不改功能也能实现 在app\Http\Kernel.php文件中编辑,增加新增的 ```php protected $routeMiddleware = [ 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'jwt.auth'=> \Tymon\JWTAuth\Middleware\GetUserFromToken::class, 'jwt.refresh'=> \Tymon\JWTAuth\Middleware\RefreshToken::class, ]; ``` 这边环境配置也就完成了 ## 初步使用 先把原来的路由注释掉,在路由中写 ```php $api=app('Dingo\Api\Routing\Router'); $api->version('v1',function($api){ //在这里面可以写我们的路由 $api->group(['namespace'=>'App\Api\Controllers'],function($api){ $api->get('lessons','LessonsController@index'); }); }); ``` 然后在app文件夹下创建Api/Controllers 这2个文件夹 在app/Api/Controllers文件夹下新建BaseController.php和LessonsController.php 编辑BaseController.php 让每个控制器继承BaseController就是让后面控制器能用dingoapi的Helpers ```php namespace App\Api\Controllers; use App\Http\Controllers\Controller; use Dingo\Api\Routing\Helpers; class BaseController extends Controller { //use Dingo\Api\Routing\Helpers; use Helpers; } ``` 编辑LessonsController.php ```php namespace App\Api\Controllers; use App\Lesson; class LessonsController extends BaseController { public function index() { return Lesson::all(); } } ``` 文件编辑好了,我们通过 `php artisan api:routes` 这个命令来查看api路由 ## transform 在Api文件夹下新建一个Transformers文件夹,新建个文件 LessonTransformers.php ~~~ namespace App\Api\Transformers; use App\Models\User; use League\Fractal\TransformerAbstract; class LessonTransformer extends TransformerAbstract { public function transform(User $user) { return [ 'id'=>$user['id'], 'username'=>$user['username'], ]; } } ~~~ 在LessonsController.php中我们这样写 ~~~ public function text() { $data=User::all(); return $this->collection($data,new LessonTransformer()); } ~~~ ### 使用JWT 我们在app\Api\Controllers这个文件夹下面新建 `AuthController.php` 编辑这个文件 ```php namespace App\Api\Controllers; use Illuminate\Http\Request; use JWTAuth; use Tymon\JWTAuth\Exceptions\JWTException; class AuthController extends BaseController { //这个方法主要负责返回我们token,有过期时间的,token做为登录标识 public function authenticate(Request $request) { // grab credentials from the request $credentials = $request->only('email', 'password'); try { // attempt to verify the credentials and create a token for the user if (! $token = JWTAuth::attempt($credentials)) { return response()->json(['error' => 'invalid_credentials'], 401); } } catch (JWTException $e) { // something went wrong whilst attempting to encode the token return response()->json(['error' => 'could_not_create_token'], 500); } // all good so return the token return response()->json(compact('token')); } } ``` 里面方法直接是复制手册的,然后我们编辑路由 ```php $api=app('Dingo\Api\Routing\Router'); $api->version('v1',function($api){ //在这里面可以写我们的路由 $api->group(['namespace'=>'App\Api\Controllers'],function($api){ $api->post('user/login','AuthController@authenticate'); $api->get('lessons','LessonsController@index'); }); }); ``` 我们用postman来模拟,在Authorization这个选项中Type选择 `Basic Auth` 里面写用户名和密码,这样发送还不行,还要在Body里面写email和对应的值,以及password和对应的值,发送过去,就可以拿到token 没有这个token访问不了JWT保护的东西 在路由中编辑 ```php $api=app('Dingo\Api\Routing\Router'); $api->version('v1',function($api){ //在这里面可以写我们的路由 $api->group(['namespace'=>'App\Api\Controllers'],function($api){ $api->post('user/login','AuthController@authenticate'); $api->post('user/register','AuthController@register'); //这边的jwt.auth是对应Kernel.php文件中的 $api->group(['middleware'=>'jwt.auth'],function($api){ //根据token获取用户信息,要用户登录,根据登录token才可获取到 $api->get('user/me','AuthController@AuthenticatedUser'); //这样这个路由就受到了jwt.auth保护,如果没有token是不行的 $api->get('lessons','LessonsController@index'); }); }); }); ``` 根据token获取用户信息(要用户登录,根据登录token才可获取到) 下面代码注意命令空间,代码直接复制手册 ```php public function getAuthenticatedUser() { try { if (! $user = JWTAuth::parseToken()->authenticate()) { return response()->json(['user_not_found'], 404); } //use Tymon\JWTAuth\Exceptions\TokenExpiredException; } catch (TokenExpiredException $e) { return response()->json(['token_expired'], $e->getStatusCode()); //use Tymon\JWTAuth\Exceptions\TokenInvalidException; } catch (TokenInvalidException $e) { return response()->json(['token_invalid'], $e->getStatusCode()); //use Tymon\JWTAuth\Exceptions\JWTException; } catch (JWTException $e) { return response()->json(['token_absent'], $e->getStatusCode()); } // the token is valid and we have found the user via the sub claim return response()->json(compact('user')); } ``` 然后访问这个api,加上?token= 问题: 如果我们数据库字段不是email和password,是user_email和user_password,我们该怎么办 编辑AuthController.php这个文件中authenticate这个方法 ```php // 注释这一行 // $credentials = $request->only('email', 'password'); $credentials =[ //get获取的 'user_email'=>$request->get('user_email'), 'password'=>$request->get('user_password'), ]; ``` 然后在User.php这个模型类中新增个方法 ```php public function getAuthPassword(){ //指向数据库字段 return $this->user_password; } ``` postman测试token时候,email和password换为user_email和user_password ## oAuth(废弃) ### 配置 github相关资料: https://github.com/xiaosier/libweibo https://github.com/liyu001989/dingo-api-wiki-zh/blob/master/Authentication.md 在composer.json中添加`"lucadegasperi/oauth2-server-laravel": "5.0.*"` 运行 `composer update` 在config/app.php中providers数组中添加 `LucaDegasperi\OAuth2Server\Storage\FluentStorageServiceProvider::class,` `LucaDegasperi\OAuth2Server\OAuth2ServerServiceProvider::class,` 在aliases数组中添加 `'Authorizer'=>LucaDegasperi\OAuth2Server\Facades\Authorizer::class,` 在app\Http\Kenel.php中middleware数组中添加`\LucaDegasperi\OAuth2Server\Middleware\OAuthExceptionHandlerMiddleware::class,` 在routeMiddleware数组中添加 ```php 'oauth'=>\LucaDegasperi\OAuth2Server\Middleware\OAuthMiddleware::class, 'oauth-user'=>\LucaDegasperi\OAuth2Server\Middleware\OAuthUserOwnerMiddleware::class, 'oauth-client'=>\LucaDegasperi\OAuth2Server\Middleware\OAuthClientOwnerMiddleware::class, 'check-authorization-params'=>\LucaDegasperi\OAuth2Server\Middleware\CheckAuthCodeRequestMiddleware::class, ``` 运行 `php artisan vendor:publish` 生成配置文件oauth2.php,运行 `php artisan migrate` 生成表 在config/api.php中编辑,如果原来这数组有东西就改了 ```php 'auth' => [ 'jwt'=>'Dingo\Api\Auth\Provider\JWT' ], ``` 在config/oauth2.php中编辑 ```php 'grant_types' => [ 'authorization_code'=>[ 'class'=>'\League\OAuth2\Server\Grant\AuthCodeGrant', 'access_token_ttl'=>3600, 'auth_token_ttl'=>3600 ] ], ``` ### 流程