# 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
]
],
```
### 流程
- 配置
- composer安装
- composer用法
- composer版本约束表达
- phpstorm
- sftp文件同步
- php类型约束
- laradock
- 配置文件缓存详解
- git
- 自定义函数
- 核心概念
- IOC
- 服务提供者
- Facade
- 契约
- 生命周期
- 路由
- 请求
- 命名路由
- 路由分组
- 资源路由
- 控制器路由
- 响应宏
- 响应
- Command
- 创建命令
- 定时任务
- console路由
- 执行用户自定义的定时任务
- artisan命令
- 中间件
- 创建中间件
- 使用中间件
- 前置和后置
- 详细介绍
- 访问次数限制
- 为 VerifyCsrfToken 添加过滤条件
- 单点登录
- 事件
- 创建
- ORM
- 简介
- DB类
- 配置
- CURD
- queryScope和setAttribute
- 查看sql执行过程
- 关联关系
- 一对一
- 一对多
- 多对多
- 远程关联
- 多态一对多
- 多态多对多
- 关联数据库的调用
- withDefault
- 跨模型更新时间戳
- withCount,withSum ,withAvg, withMax,withMin
- SQL常见操作
- 模型事件
- 模型事件详解
- 模型事件与 Observer
- deleted 事件未被触发
- model validation
- ORM/代码片段
- Repository模式
- 多重where语句
- 中间表类型转换
- Collection集合
- 新增的一些方法
- 常见用法
- 求和例子
- 机场登机例子
- 计算github活跃度
- 转化评论格式
- 计算营业额
- 创建lookup数组
- 重新组织出表和字段关系并且字段排序
- 重构循环
- 其他例子
- 其他问题一
- 去重
- 第二个数组按第一个数组的键值排序
- 搜索ES
- 安装
- 表单
- Request
- sessiom
- Response
- Input
- 表单验证
- 简介
- Validator
- Request类
- 接口中的表单验证
- Lumen 中自定义表单验证返回消息
- redis
- 广播事件
- 发布订阅
- 队列
- 守护进程
- redis队列的坑
- beanstalkd
- rabbitmq
- redis队列
- 日志模块
- 错误
- 日志详解
- 数据填充与迁移
- 生成数据
- 数据填充seed
- migrate
- 常见错误
- Blade模板
- 流程控制
- 子视图
- URL
- 代码片段
- Carbon时间类
- 一些用法
- 邮件
- 分页
- 加密解密
- 缓存
- 文件上传
- 优化
- 随记
- 嵌套评论
- 判断字符串是否是合法的 json 字符串
- 单元测试
- 计算出两个日期的diff
- 自定义一个类文件让composer加载
- 时间加减
- 对象数组互转方法
- 用户停留过久自动退出登录
- optional 辅助方法
- 文件下载
- Api
- Dingo api
- auth.basic
- api_token
- Jwt-Auth
- passport
- Auth
- Authentication 和 Authorization
- Auth Facade
- 授权策略
- Gates
- composer包
- debug包
- idehelp包
- image处理
- 验证码
- jq插件
- 第三方登录
- 第三方支付
- log显示包
- 微信包
- xss过滤
- Excel包
- MongoDB
- php操作
- 聚合查询
- 发送带附件邮件
- 中文转拼音包
- clockwork网页调试
- emoji表情
- symfony组件
- swooletw/laravel-swoole
- 常见问题
- 跨域问题
- Laravel队列优先级的一个坑
- cache:clear清除缓存问题
- .env无法读取
- 源码相关基础知识
- __set和__get
- 依赖注入、控制反转和依赖倒置原则
- 控制反转容器(Ioc Container)
- 深入服务容器
- call_user_func
- compact
- 中间件简易实现
- array_reduce
- 中间件实现代码
- Pipeline管道操作
- composer自动加载
- redis延时队列
- 了解laravel redis队列
- cli
- 源码解读
- Facade分析
- Facade源码分析
- IOC服务容器
- 中间件原理
- 依赖注入浅析
- 微信
- 微信公众号
- 常用接收消息
- 6大接收接口
- 常用被动回复消息
- 接口调用凭证
- 自定义菜单
- 新增素材
- 客服消息
- 二维码
- 微信语音
- LBS定位
- 网页授权
- JSSDK
- easywechat
- 小程序
- 小程序配置app.json