第一节 部署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的继承类如下:
/**
* @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 文件 然后编辑如下代码
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 用于作为被继承的验证基础模块,代码如下:
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
认证模块分为登录、注册、获取用户信息 ,全部代码如下:
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文件代码如下:
/**该类为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作为基础信息获取,代码如下:
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