前言

距上次使用Laravel + jwt 已经好久了,依稀记得当时很惨烈,各种文档不全看不懂,最后照着网上搜来的一个教程一步一步不知所云的才勉勉强强上线,那会用的还是laravel 5,这次弥补一下遗憾,重新自己挖坑 填坑来一次!

Ps:最近感受到了composer管理包带来的便利性,开始多多加强composer的使用和学习

准备工作

  • laravel/laravel:6.8
  • tymon/jwt-auth:1.0.0-rc.5

    • 这个版本支持laravel 6

安装

在项目中直接require即可

composer require tymon/jwt-auth:1.0.0-rc.5

Composer 安装时内存不足失败

俩种选择,换一个内存大的环境对项目进行安装,比如本地
或者增加环境的虚拟内存大小

/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
/sbin/mkswap /var/swap.1
/sbin/swapon /var/swap.1

以上操作需要root权限
如果你之前已经有swap交换文件了,执行以上步骤后会自动累加


重启后新增的交换文件不会自动挂载,需要手动执行以下俩步操作或者放在开机脚本内

/sbin/mkswap /var/swap.1
/sbin/swapon /var/swap.1

相关文档:
https://jwt-auth.readthedocs.io/en/develop/laravel-installation/
https://learnku.com/articles/10885/full-use-of-jwt

调试Jwt

第一步:安装好后,生成一个key

php artisan jwt:secret

第二步:把配置文件迁移到 config/ 下

配置挪出来,保证一致性,原位置在vender中,会被gitignore忽略

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

第三步:修改用户模型

Jwt验证是和用户的模型相关联的,需要修改你的用户模型

这是原始的user模型(框架自带的)

引入 JWTSubject,并让模型去实现 JWTSubject

这里删除了邮箱验证 MustVerifyEmail


添加俩个方法,用户模型修改完成

第四步:添加Facade (可选)

laravel的配置文件 config/app.php中的aliases下添加
也可以使用laravel 的辅助函数 auth(), 这里我不添加

'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,

第五步:修改 auth.php

修改默认值:guard下默认的web 改成 api

apidriver,更换成我们要使用的jwt
provider选择用户模型的提供者

上图提到的提供者在下面定义,把我们修改好的用户模型绑定到model

以下来自官方机翻

在这里,我们告诉api后卫使用jwt驱动程序,并将api后卫设置为默认值。
现在,我们可以使用Laravel内置的Auth系统,通过jwt-auth进行幕后工作!

到此,JWT 配置完了,看看怎么使用吧!

使用 JWT

第一步 jwt的作用

其实状态无非就是以下几种:

  • 生成 token :把用户和token绑定在一起 => 用户的“密码”
  • 验证 token :ok => “登录”成功
  • token过期 :把用户“密码”删了
  • token 过期了:“登录”超时
  • 刷新 token:把“密码”的过期时间延期

第二步 token的使用

因为没有添加 jwtFacades, 下面全部使用laravel的函数 auth()
如果 guard的默认值是 api(我们前俩步已经改好了),我们就可以直接使用auth()

如需指定其他guard设备,使用auth('qita')括号内指定即可

并且部分方法还可方便的直接使用静态 auth::id(). 以下 auth:: 全部可用 auth()-> 替换

A. 生成token:

  • 使用用户模型生成
    $token = auth()->login($userModel);
  • 使用模型的用户主键 id 生成
    $token = auth()-> tokenById('id');
  • 验证账号密码然后生成
    $token = auth()-> attempt(['账号','密码']);
  • 生成时携带载荷
    $claims = ['mes'=>'lihai','code'=>'1001'];
    $token = auth()->claims($claims)->login($user);

B. 验证token:

token的验证是基于中间件的自动验证,可选jwt的中间件或laravel的中间件

JWT中间件:

引用自learnku@skyArony 第一二个功能一样,但是第二个不会抛出错误,第三四个功能一样,没什么区别。
protected $middlewareAliases = [
    'jwt.auth' => Authenticate::class,
    'jwt.check' => Check::class,
    'jwt.refresh' => RefreshToken::class,
    'jwt.renew' => AuthenticateAndRenew::class,
];

laravel中间件 auth:api:

有一点需要注意,需要到./Exceptions/Handler.php 重写以下方法,自定义验证失败操作(默认验证失败跳到login路由)
public function unauthenticated($request, $exception)
{
    return $request->expectsJson()
        ? response()->json(['message' => 'Unauthenticated.'], 401)
        : response()->json(['mes'=>'token验证失败','code'=>'96104'],401);
}

中间件也需设置 .../Middleware/Authenticate.php

protected function redirectTo($request)
{
    if (! $request->expectsJson()) {
          // return route('login');
          return null;
    }
}

C. 使用Token

  • 使用其验证

    加到网址中 => 相当于明文

    ?token=token

    加到 header中 => 在 https下是加密的

    Authorization:Bearer token

  • 使用其解析

    获取 token中的 user对象

    $user = auth::user();

    获取 token中的 userid

    $userid = auth::id();

    解析 token的信息 (如果设置了载荷就会解析出来)

    $info = auth::payload()->toarray();

    array:8 [
    "iss" => "http://wb.com/api/login"
    "iat" => 1577167749 # 签发时间
    "exp" => 1577171349 # 过期时间
    "nbf" => 1577167749 # 生效时间
    "jti" => "Kf4000hFaYYNMC7x"
    "sub" => 7
    "prv" => "8e744acf675a27367db01824c52901256f6ba54a"
    "niubi" => "hehe" # 载荷
    ]

D. 删除Token

# 退出登录
auth::logout();
# 加到黑名单
auth()->invalidate()

E. 刷新Token

# 刷新token 拿到新的,旧的失效(可设置宽限时间)
$token = auth::refresh();

第三步 写一个token的基本控制器

php artisan make:controller AuthController

待续