laravel 5.4 JWT + Dingo 构建API 攻略

第一节 部署laravel项目到本地 配置JWT 和 Dingo
①直接使用composer 下载laravel到本地 (composer 安装教程 baidu 吧)
执行:

composer create-project laravel/laravel --prefer-dist

②在composer.json的require字段中添加:”dingo/api”:”1.0.*@dev”
执行:

composer update

③在config/app.php注册到providers数组:

'providers'=>[
Dingo\Api\Provider\LaravelServiceProvider::class,
]

④生成dingo配置文件config/api.php :

php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"

⑤.env添加基础配置(四个即可):

API_STANDARDS_TREE=vnd 
API_SUBTYPE=ssapi      
API_PREFIX=api         
API_VERSION=v1        
API_NAME=ssapi     
API_CONDITIONAL_REQUEST=false  
API_STRICT=false
API_DEFAULT_FORMAT=json
API_DEBUG=true 

API_STANDARDS_TREE - API规格 ①x 本地或私有环境 ②prs非商业销售的项目 ③vnd 公开的以及商业销售的项目
API_SUBTYPE - API简称
API_PREFIX - API前缀(或使用API_DOMAIN - API子域名)
API_VERSION - API 默认版本
API_NAME - API名称
API_CONDITIONAL_REQUEST - 带条件的请求,由于缓存API请求的时候会使用客户端缓存功能,所以默认开启了带条件的请求
API_STRICT - 严格模式,要求客户端发送Accept头而不是默认在配置文件中指定的版本
解释一下:因为我们不在 URI 中指定具体的版本,所以我们需要定义 Accept 头去请求具体的版本。头信息格式如下。
Accept: application/vnd.YOUR_SUBTYPE.v1+json
API_DEFAULT_FORMAT - 响应格式,默认的响应格式是JSON
API_DEBUG - 调试模式

⑥在composer.json的require字段中添加:”tymon/jwt-auth”:”0.5.*”
执行:
composer update

⑦在config/app.php注册到providers数组:

'providers'=>[
    Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
]

⑧注册jwt门面:

'aliases'=>[
    'JWTAuth'=> Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory'=> Tymon\JWTAuth\Facades\JWTFactory::class
]

⑨生成jwt配置文件config/jwt.php :

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

⑩生成jwt.php文件中数组的secret键成对应的值:

php artisan jwt:generate

最后关联dingo与JWT 修改config/api.php的auth如下:

'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']);  
    }  
], 

稍微放松一下 准备第二节

第二节 JWT + Dingo 与laravel 在代码层面的实际操作

①新建数据库及其model
1. 新建migrate: 新建account表

 php artisan make:migration create_account_table --create=accounts  

2 新建model:

php artisan make:model Account

3.然后修改model Account的继承类如下:

<?php

namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;


/**
 * @property mixed password
 */
class Account extends Authenticatable
{
    protected $fillable = ['id','name','email','password'];

}

4.修改data/migrations/201x_xx_xx_xxxxxx_create_accounts_table.php文件中的up方法如下:

public function up()
    {
        Schema::create('accounts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name',50);
            $table->string('password',100);
            $table->string('email',50);
            $table->timestamps();
        });
    }

5.然后

php artisan migrate

的测试数据表就建好了。(执行之前请清除migrations文件夹下面的原有.php文件 例如2014_xx_xx_xxxxxxxxxxx.php文件)
(执行时候报错的话↓ 以下错误 请去配置 .env 文件的数据库部分 )
DB_DATABASE=laravel-api-demo
DB_USERNAME=root
DB_PASSWORD=root

[Illuminate\Database\QueryException]                                                                                                                                                                   
  SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES) (SQL: select * from information_schema.tables where table_schema = homestead and table_name = migrations)  

  [PDOException]                                                                               
  SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES)  

6.然后我们需要修改config/jwt.php中”user”=>”App\User”如下:

'user' => 'App\Account',  

② 添加代码
1.在routes/api.php 添加以下代码

$api = app('Dingo\Api\Routing\Router');
$api->version('v1', function ($api) {
    $api->group(['namespace' => 'App\Api\Controllers','middleware' => ['account.change']], function ($api) {
        $api->post('user/login', 'AuthController@authenticate');  //登录授权
        $api->post('user/register', 'AuthController@register');
        $api->group(['middleware' => 'jwt.auth'], function ($api) {


            $api->post('tests', 'TestsController@index');
            //路径为 /api/tests
            //get post 请求 都可以
            //header头中加入 Authorization Bearer your_token  测试成功


             //请求方式:
            //http://localhost:8000/api/tests?token=xxxxxx  (从登陆或注册那里获取,目前只能用get)
            $api->get('tests/{id}', 'TestsController@show');
            $api->get('user/me', 'AuthController@AuthenticatedUser'); //根据
        });
    });
});

上面使用了一个account.change中间件 下面我们定义这个中间件
2.执行

php artisan make:middleware AccountChange

这时候会生成 app/Http/Middleware/AccountChange.php 文件 然后编辑如下代码

<?php

namespace App\Http\Middleware;

use Closure;

class AccountChange
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        config(['jwt.user' => '\App\Account']);    //重要用于指定特定model
        config(['auth.providers.users.model' => \App\Account::class]);//重要用于指定特定model!!!!
        return $next($request);
    }
}

3.然后去Kernel.php 注册中间件 account.change
在app/Http/Kernel.php 中 protected $routeMiddleware = [] 中添加一行

 'account.change' => \App\Http\Middleware\AccountChange::class,

捎带加入两个在使用token 进行反向验证时候需要用到的连个中间件:

 'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,
 'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class,

4.继续添加代码
首先在app目录下创建Api/Controllers及Api/Transformers目录,图如下:
这里写图片描述
然后在Controllers下创建BaseController.php 用于作为被继承的验证基础模块,代码如下:

<?php  

namespace App\Api\Controllers;  

use App\Http\Controllers\Controller;  
use Dingo\Api\Routing\Helpers;  


class BaseController extends Controller  
{  
    use Helpers;  

    /**** 
     * BaseController constructor. 
     */  
    public function __construct()  
    {  

    }  
}  

5.认证模块添加
创建文件 app/Api/Controllers/AuthController.php
认证模块分为登录、注册、获取用户信息 ,全部代码如下:

<?php

namespace App\Api\Controllers;

use App\Account;
use Illuminate\Http\Request;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;


class AuthController extends BaseController
{
    /**
     * The authentication guard that should be used.
     *
     * @var string
     */
    public function __construct()
    {
        parent::__construct();

    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function authenticate(Request $request)
    {
        $payload = [
            'email' => $request->get('email'),
            'password' => $request->get('password')
        ];
        try {
            if (!$token = JWTAuth::attempt($payload)) {
                return response()->json(['error' => 'token_not_provided'], 401);
            }
        } catch (JWTException $e) {
            return response()->json(['error' => '不能创建token'], 500);
        }
        return response()->json(compact('token'));
    }

    /**
     * @param Request $request
     */
    public function register(Request $request)
    {
        $newUser = [
            'email' => $request->get('email'),
            'name' => $request->get('name'),
            'password' => bcrypt($request->get('password'))
        ];
        $user = Account::create($newUser);
        $token = JWTAuth::fromUser($user);
        return $token;
    }

    /****
     * 获取用户的信息
     * @return \Illuminate\Http\JsonResponse
     */
    public function AuthenticatedUser()
    {
        try {
            if (!$user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (TokenExpiredException $e) {
            return response()->json(['token_expired'], $e->getStatusCode());
        } catch (TokenInvalidException $e) {
            return response()->json(['token_invalid'], $e->getStatusCode());
        } 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'));
    }
}  

过程分析:
①继承自BaseController.php,继承了dingo的操作方法
②继承BaseController.php的构造函数,并用config改变其指定model
③到这里如果没有配置错误的话就是就是三个模块都可以正常运行了

6.认证模块使用讲解
postman 接口工具 自行下载

首先 请求localhost:8000/api/user/register 注册接口:
这里写图片描述

接收到返回值 token;

然后请求 localhost:8000/api/user/login 请求如下图:
这里写图片描述

如上图 登陆成功 获取到token;

同样我们得到了一个新的token,这里说明每次登陆都会刷新token这样我们复制最新token,下面有用

接下来 使用刚登陆获取到的token 得到对应的个人信息
这里写图片描述
注意看请求url 带的参数

7.token获取信息模块

第6步中最后一个获取个人信息模块也属于这里。。。下面主要讲解返回特定的数据格式
首先在Transformers目录下添加TestsTransformer.php文件代码如下:

<?php  

namespace App\Api\Transformers;  

/**该类为dingo api封装好**/  
use League\Fractal\TransformerAbstract;  

class TestsTransformer extends TransformerAbstract  
{  
    /*** 
     * 分开为了解耦 
     * 数据字段选择 
     * @param $lesson 
     * @return array 
     */  
    public function transform($lesson)  
    {  
        /******隐藏数据库字段*****/  
        return [  
            'username' => $lesson['user_name'],  
            'email' => $lesson['user_email'],  
        ];  
    }  
}  

注:这里继承了dingo的TransformerAbstract类
然后在Controllers目录下新建TestsController.php作为基础信息获取,代码如下:

<?php
namespace App\Api\Controllers;


use App\Api\Transformers\TestsTransformer;
use App\Account;

class TestsController extends BaseController
{
    public function index()
    {
        $tests = Account::all();
        return $this->collection($tests, new TestsTransformer());
    }

    public function show($id)
    {
        $test = Account::find($id);
        if (!$test) {
            return $this->response->errorNotFound('Test not found');
        }
        return $this->item($test, new TestsTransformer());
    }
}  

注:这里引用了TestsTransformer作为数据格式,item为dingo自带函数,处理数据格式并返回

这个时候我们请求 localhost:8000/api/tests
注意: 这个时候我们是使用token 通过token的验证 再去获取数据
在请求url的时候 需要在 Header 头中加入一些信息 详细看下图
这里写图片描述
其中Authorization 为header头中的key
value 为 Bearer your_token

8.在V1 V2 。。。 的版本切换
这个时候需要在header 头中再加入一个字段 key为 Accept
value 为Accept: application/vnd.YOUR_SUBTYPE.v1+json

YOUR_SUBTYPE 为你在.env 中配置的 API_SUBTYPE 的值 v1可想而知就是你的版本喽
这里写图片描述

这里我修改了 api.php 中的一些代码 这里只是测试一下 当你在正常项目中是需要在Api目录下新建V1 文件夹和V2文件夹 这个时候你就不用担心你的api 会请求一个conteoller了
比如在V1 中你有一个usercontroller 在V2版本中 你好是需要请求usercontroller 这个时候你需要在v2文件夹下重新开始新建一个user 同时还要注意api的路由和命名空间的使用

$api->version('v2', function ($api) {
    $api->group(['namespace' => 'App\Api\Controllers','middleware' => ['account.change']], function ($api) {

        $api->group(['middleware' => 'jwt.auth'], function ($api) {


            $api->post('tests', 'TestsController@index');
            //路径为 /api/tests
            //get post 请求 都可以
            //header头中加入 Authorization Bearer your_token  测试成功

        });
    });
});

以上为本次laravel-dingo-jwt的学习笔记

本文引用http://blog.csdn.net/qq_28666081/article/details/52187612 部分 修改了一写 该文章的BUG

附上
https://github.com/liyu001989/dingo-api-wiki-zh/blob/master/Making-Requests-To-Your-API.md 中文翻译的dingo文档
更多详细文档https://github.com/dingo/api

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值