关于laravel中表关系的一对一、一对多、多对一、多对多实践(转)_武功秘籍大全

【PHP】Laravel JWT完整使用教程

一、JWT 简单介绍

JWT 全称 JSON Web Tokens ,是一个非常轻巧的规范。这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。它的两大使用场景是:认证和数据交换。

以下步骤都是经过本人自研项目实践过,大家可以放心参考;

二、安装之前

主要使用的扩展及参考资料:

  • PHP-Open-Source-Saver/jwt-auth
  • JWT 完整使用详解
  • JWT的介绍
  • 官方安装指导文件

三、安装及配置

1)使用 composer 安装

composer require php-open-source-saver/jwt-auth

2)进行一些配置

)发布配置文件

这条命令会在 config 下增加一个 jwt.php 的配置文件

php artisan vendor:publish --provider=&#;PHPOpenSourceSaver\JWTAuth\Providers\LaravelServiceProvider&#;

)生成加密密钥

这条命令会在 .env 文件下生成一个加密密钥,如:JWT_SECRET=foobar

php artisan jwt:secret

)生成证书(可选)

这一步可不配置,但配置后生成的 Token 会根据证书文件来生成,更加安全;详细可看官方安装指导里的说明。

php artisan jwt:generate-certs

)更新你的模型

如果你使用默认的 User 表来生成 Token,你需要在该模型下增加一段代码
app/Models/User.php


<?php

namespace App;

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

class User extends Authenticatable implements JWTSubject    # 这里别忘了加
{
    use Notifiable;

    // 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 [];
    }
}

)注册两个 Facade

这两个 Facade 并不是必须的,但是使用它们会给你的代码编写带来一点便利。
config/app.php


&#;aliases&#; => [
        ...
        // 添加以下两行
        &#;JWTAuth&#; => &#;Tymon\JWTAuth\Facades\JWTAuth&#;,
        &#;JWTFactory&#; => &#;Tymon\JWTAuth\Facades\JWTFactory&#;,
],

如果你不使用这两个 Facade,你可以使用辅助函数 auth ()
auth () 是一个辅助函数,返回一个 guard,暂时可以看成 Auth Facade。


// 如果你不用 Facade,你可以这么写
auth(&#;api&#;)->refresh();
// 用 JWTAuth Facade
JWTAuth::parseToken()->refresh();

两个 Facede 常用可使用方法,可以看文章后面的附录。

)修改 auth.php

config/auth.php


&#;guards&#; => [
    &#;web&#; => [
        &#;driver&#; => &#;session&#;,
        &#;provider&#; => &#;users&#;,
    ],

    &#;api&#; => [
        &#;driver&#; => &#;jwt&#;,        // 原来是 token 改成jwt
        &#;provider&#; => &#;users&#;,
    ],
],

)创建 Auth 控制器

php artisan make:controller AuthController
app/Http/Controllers/AuthController.php
值得注意的是 Laravel 这要用 auth(&#;api&#;)。


<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;

class AuthController extends Controller
{
    /**
     * Create a new AuthController instance.
     * 要求附带email和password(数据来源users表)
     * 
     * @return void
     */
    public function __construct()
    {
          // 这里额外注意了:官方文档样例中只除外了『login』
          // 这样的结果是,token 只能在有效期以内进行刷新,过期无法刷新
          // 如果把 refresh 也放进去,token 即使过期但仍在刷新期以内也可刷新
          // 不过刷新一次作废
        $this->middleware(&#;jwt.auth&#;, [&#;except&#; => [&#;login&#;]]);
          // 另外关于上面的中间件,官方文档写的是『auth:api』
          // 但是我推荐用 『jwt.auth』,效果是一样的,但是有更加丰富的报错信息返回
    }

    /**
     * Get a JWT via given credentials.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login()
    {
        $credentials = request([&#;email&#;, &#;password&#;]);

        if (! $token = auth(&#;api&#;)->attempt($credentials)) {
            return response()->json([&#;error&#; => &#;Unauthorized&#;], );
        }

        return $this->respondWithToken($token);
    }

    /**
     * Get the authenticated User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        return response()->json(auth(&#;api&#;)->user());
    }

    /**
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth(&#;api&#;)->logout();

        return response()->json([&#;message&#; => &#;Successfully logged out&#;]);
    }

    /**
     * Refresh a token.
     * 刷新token,如果开启黑名单,以前的token便会失效。
     * 值得注意的是用上面的getToken再获取一次Token并不算做刷新,两次获得的Token是并行的,即两个都可用。
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(auth(&#;api&#;)->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&#; => auth(&#;api&#;)->factory()->getTTL() * 
        ]);
    }
}

四、JWT Token 详解

1)Token 创建

前面的 AuthController.php 中有两行展现了这一种 Token 的创建方法,即用用户所给的账号和密码进行尝试,密码正确则用对应的 User 信息返回一个 Token 。

但 Token 的创建方法不止这一种,接下来介绍 Token 的三种创建方法:

  • 基于账密参数
  • 基于 users 模型返回的实例
  • 基于 users 模型中的用户主键 id

a)基于账密参数

这就是刚刚说的哪一种,贴出具体代码。


// 使用辅助函数
$credentials = request([&#;email&#;, &#;password&#;]); 
$token = auth()->attempt($credentials)

// 使用 Facade
$credentials = $request->only(&#;email&#;, &#;password&#;);
$token = JWTAuth::attempt($credentials);

b)基于 users 模型返回的实例


// 使用辅助函数
$user = User::first();
$token = auth()->login($user);

// 使用 Facade
$user = User::first();
$token = JWTAuth::fromUser($credentials);

c)基于 users 模型中的主键 id


// 使用辅助函数
$token = auth()->tokenById(1);

// 使用 Facade
源码中没找到

2)Token 的解析

a)解析 Token 到对象

只有 Facade 需要这样。


// 把请求发送过来的直接解析到对象
JWTAuth::parseToken();

b)获取 Token 中的 user 信息


// 辅助函数
$user = auth()->user();

// Facade
$user = JWTAuth::parseToken()->authenticate();

c)获取 Token

如果 token 被设置则会返回,否则会尝试使用方法从请求中解析 token ,如果 token 未被设置或不能解析最终返回 false。


// 辅助函数
$token = auth()->getToken();

// Facade
$token = JWTAuth::parseToken()->getToken();

更多方法可以看官方安装指南文件。

五、Token 的三个时间

一个 Token 一般来说有三个时间属性,其配置都在 config/jwt.php 内。

有效时间

有效时间指的的是你获得 Token 后,在多少时间内可以凭这个 Token 去获取内容,逾时无效。


// 单位:分钟
&#;ttl&#; => env(&#;JWT_TTL&#;, )

刷新时间

刷新时间指的是在这个时间内可以凭旧 Token 换取一个新 Token。例如 Token 有效时间为 分钟,刷新时间为 分钟,在 分钟内可以通过这个 Token 获取新 Token,但是超过 分钟是不可以的,然后你可以一直循环获取,直到总时间超过 分钟,不能再获取。


// 单位:分钟
&#;refresh_ttl&#; => env(&#;JWT_REFRESH_TTL&#;, )

宽限时间

宽限时间是为了解决并发请求的问题,假如宽限时间为 0s ,那么在新旧 token 交接的时候,并发请求就会出错,所以需要设定一个宽限时间,在宽限时间内,旧 Token 仍然能够正常使用。


// 宽限时间需要开启黑名单(默认是开启的),黑名单保证过期token不可再用,最好打开
&#;blacklist_enabled&#; => env(&#;JWT_BLACKLIST_ENABLED&#;, true)

// 设定宽限时间,单位:秒
&#;blacklist_grace_period&#; => env(&#;JWT_BLACKLIST_GRACE_PERIOD&#;, )
原文链接:,转发请注明来源!