# 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可能遇到個問題

安裝上面來就可以
在.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