Laravel5+dingo+jwt 开发后台API

发布 : 2019-05-30 分类 : 后端 浏览 :

1. composer.json 引入包,执行 composer update

1
2
3
4
5
"require": {
......
"dingo/api": "^2.1",
"tymon/jwt-auth": "^1.0.0-rc.1"
},

2. 执行下面两个语句自动生成 dingo 和 jwt 的配置文件

1
2
php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
//config文件夹中生成dingo配置文件---> api.php
1
2
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
//config文件夹中生成dingo配置文件---> jwt.php

3. 配置.env

1
2
3
4
5
API_STANDARDS_TREE=vnd
API_PREFIX=api
API_VERSION=v1
API_DEBUG=true
API_SUBTYPE=myapp

具体配置参考:https://www.bookstack.cn/read/dingo-api-wiki-zh/Configuration.md

还需在命令行执行 php artisan jwt:secret,会在.env 自动添加 JWT_SECRET,其他若需要,可以到各种的配置文件中看,在.env 添加即可

4. 关键处理

编辑auth.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],

'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],

这里需要把 api 原本的 driver => token 改为使用 jwt 机制,provider 对应你要用的用户认证表,一般就是登录注册那张表

Models/User.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php

namespace App\Models;

use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements JWTSubject {
use Notifiable;

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password', 'unionid'
];

/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];

// Rest omitted for brevity

/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier() {
return $this->getKey();
}

/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims() {
return [];
}
}

5. 设置控制器

在app目录下新建Api目录,用于管路Api相关业务代码,新建AuthController控制器,注意命名空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php
/**
* Date: 17/10/12
* Time: 01:07
*/

namespace App\Http\Controllers\V1;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use App\User;

class AuthController extends Controller
{

protected $guard = 'api';//设置使用guard为api选项验证,请查看config/auth.php的guards设置项,重要!

/**
* Create a new AuthController instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('refresh', ['except' => ['login','register']]);
}

public function test(){
echo "test!!";
}

public function register(Request $request)
{

$rules = [
'name' => ['required'],
'email' => ['required'],
'password' => ['required', 'min:6', 'max:16'],
];

$payload = $request->only('name', 'email', 'password');
$validator = Validator::make($payload, $rules);

// 验证格式
if ($validator->fails()) {
return $this->response->array(['error' => $validator->errors()]);
}

// 创建用户
$result = User::create([
'name' => $payload['name'],
'email' => $payload['email'],
'password' => bcrypt($payload['password']),
]);

if ($result) {
return $this->response->array(['success' => '创建用户成功']);
} else {
return $this->response->array(['error' => '创建用户失败']);
}

}

/**
* Get a JWT token via given credentials.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\JsonResponse
*/
public function login(Request $request)
{
$credentials = $request->only('email', 'password');

if ($token = $this->guard()->attempt($credentials)) {
return $this->respondWithToken($token);
}

return $this->response->errorUnauthorized('登录失败');
}

/**
* Get the authenticated User
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
//return response()->json($this->guard()->user());
return $this->response->array($this->guard()->user());
}

/**
* Log the user out (Invalidate the token)
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
$this->guard()->logout();

//return response()->json(['message' => 'Successfully logged out']);
return $this->response->array(['message' => '退出成功']);
}

/**
* Refresh a token.
*
* @return \Illuminate\Http\JsonResponse
*/
public function refresh()
{
return $this->respondWithToken($this->guard()->refresh());
}

/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => $this->guard()->factory()->getTTL() * 60
]);
}

/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\Guard
*/
public function guard()
{
return Auth::guard($this->guard);
}
}

6. refresh 中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php

namespace App\Http\Middleware;

use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

class RefreshToken extends BaseMiddleware
{
/**
* @author: zhaogx
* @param $request
* @param Closure $next
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|mixed
* @throws JWTException
*/
public function handle($request, Closure $next)
{
// 检查此次请求中是否带有 token,如果没有则抛出异常。
$this->checkForToken($request);

// 使用 try 包裹,以捕捉 token 过期所抛出的 TokenExpiredException 异常
try {
// 检测用户的登录状态,如果正常则通过
if ($this->auth->parseToken()->authenticate()) {
return $next($request);
}
throw new UnauthorizedHttpException('jwt-auth', '未登录');
} catch (TokenExpiredException $exception) {
// 此处捕获到了 token 过期所抛出的 TokenExpiredException 异常,我们在这里需要做的是刷新该用户的 token 并将它添加到响应头中
try {
// 刷新用户的 token
$token = $this->auth->refresh();
// 使用一次性登录以保证此次请求的成功
\Auth::guard('api')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']);
} catch (JWTException $exception) {
// 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
}
}

return $next($request)->withHeaders([
'Authorization'=> 'Bearer '.$token,
]);
}
}

写好中间件后需要在 app/Http/Kernel.php 中注入

1
2
3
4
protected $routeMiddleware = [
​ ......
'refresh' => RefreshToken::class,
];

7. routes/api.php 设置路由

1
2
3
4
5
6
7
8
9
10
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', ['namespace' => 'App\Http\Controllers\V1'], function ($api) {
$api->post('register', 'AuthController@register');
$api->post('login', 'AuthController@login');
$api->post('logout', 'AuthController@logout');
$api->post('refresh', 'AuthController@refresh');
$api->post('me', 'AuthController@me'); //这种写法会报错
$api->post ('me', 'AuthController@me')->middleware ('refresh'); //这种写法不报错
$api->get('test', 'AuthController@test');
});

根据以上几个步骤就可以建立起简单的 api 后台基础,获取 api 路由列表可以使用命令行:

1
php artisan api:routes

知识 & 情怀 | 二者兼得

微信扫一扫, 向我投食

微信扫一扫, 向我投食

支付宝扫一扫, 向我投食

支付宝扫一扫, 向我投食

留下足迹