记录一次laravel5.8开发的API接口,引入JWT的流程。
laravel+JWT的整合教程在网上有很多,根据网上的教程整合期间,还是踩了很多坑。
虽然这些坑都能在网上搜索到解决办法,但网上的其他教程都没有注明需要注意的点在哪里。
开始之前,先放两个链接。
jwt-auth for laravel的安装与使用.
JWT 完整使用详解【这篇很详细,讲得也很到位,基本看这篇就够了】.
我也是根据这几篇文章进行的整合。
laravel中使用的是jwt-auth库,那么先安装:
step1:
# 建议使用1.0以上版本
composer require tymon/jwt-auth
step2:发布配置文件
# 这条命令会在 config 下增加一个 jwt.php 的配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
step3: 生成加密密钥
# 这条命令会在 .env 文件下生成一个加密密钥,如:JWT_SECRET=foobar
php artisan jwt:secret
step4:更新校验用户登录的模型
以User为例:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* 可以被批量赋值的属性.
* @var array
*/
protected $fillable = [];
protected $hidden = [];
/**
* 关联到模型的数据表
*
* @var string
*/
protected $table = '';
/**
* 表明模型是否应该被打上时间戳
*
* @var bool
*/
public $timestamps = false;
/**
* 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 [];
}
/**
* 覆盖Laravel中默认的getAuthPassword方法, 可返回自己需要的字段.
* @return array
public function getAuthPassword(){
return ['password'=>$this->attributes['password'], 'phone'=>$this->attributes['phone']];
}*/
}
当然,这里也可以不用user,你可以创建你自己的用于登录校验的模型。
后面jwt-auth进行登录校验时,会使用到这个模型。
step5: 修改auth.php
// 这里定义可以用的 guard(看守器)
// driver 指的就是上面的对 Guard 契约的具体实现那个类了
// users 是下面 providers 数组 key 为 users 的那个
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // 这里原是token,改为jwt
'provider' => 'users', // 这里的user指的是下面providers中配置的users
//'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent', // 这里使用的用户提供器,默认是EloquentUserProvider.
'model' => App\User::class, // 这个的作用是指定认证所需的 user 来源的数据表,可根据需要修改为你自己需要认证用户的模型.
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
划重点:
1. 因为是用的API接口,使用guards(看守器)中的api中的driver要改为jwt.
2. providers中users中配置的model,需指向关联用户的模型。关联用户的模型需extends Illuminate\Foundation\Auth\User 并 implements JWTSubject,并重写getJWTIdentifier()和getJWTCustomClaims(),如上面的User模型。
以上就是配置过程。
好,接下来,我们就来看看laravel中怎么使用jwt。
先来个controller,同样来自这个JWT 完整使用详解【这篇很详细,讲得也很到位,基本看这篇就够了】:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Tymon\JWTAuth\Facades\JWTAuth;
use Log;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
* 要求附带email和password(数据来源users表)
*
* @return void
*/
public function __construct()
{
// 这里额外注意了:官方文档样例中只除外了『login』
// 这样的结果是,token 只能在有效期以内进行刷新,过期无法刷新
// 如果把 refresh 也放进去,token 即使过期但仍在刷新期以内也可刷新
// 不过刷新一次作废
//$this->middleware('auth:api', ['except' => ['login']]);
// 另外关于上面的中间件,官方文档写的是『auth:api』
// 但是我推荐用 『jwt.auth』,效果是一样的,但是有更加丰富的报错信息返回
// auth:api auth指的是中间件 App\Http\Kernel中$routeMiddleware定义的。而后面 :api 是路由参数,指定了要使用哪个看守器,可以看到下面 api 对应的看守器就是 jwt 的看守器。
// 并且你可以直接使用 auth ,这样就相当于使用 defaults 中指定的看守器,即 session。
// Lumen 默认用的就是 api 那个,所以你直接用 auth 作为 api 路由的中间件完全没问题
// Laravel 中指定了两个看守器,而且默认的并不是 api,所以你必须得用 auth:api 作为路由的中间件
}
/**
* Get a JWT via given credentials.
*
* @return \Illuminate\Http\JsonResponse
*/
public function login()
{
$credentials = request(['phone', 'password']);
/*
* 这里创建token有三种方式
* 1. 基于账密参数
**/
$token = auth('api')->attempt($credentials);
/* 2. 基于 users 模型返回的实例
$user = User::where([
['phone', $credentials['phone'], ['password', $credentials['password']]]
])->first();
$token = auth('api')->login($user);
*/
/* 3. 基于 users 模型中的主键 id
$token = auth('api')->tokenById($user->id);
*/
if (!$token) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60,
]);