aliirfaan/laravel-simple-jwt

在Laravel中生成和验证Json Web Token (JWT)

8.1.1 2023-06-19 07:18 UTC

This package is auto-updated.

Last update: 2024-09-30 01:57:40 UTC


README

此包允许您生成JSON Web Tokens。然后您可以验证JWT代码并根据其有效性授予访问权限。您还可以使用可选的刷新令牌流来实现长会话。您可以直接在控制器中生成和验证JWT或使用提供的认证守卫。

JWT流程

  • 用户登录并获得带有自定义声明的JWT
  • 对于每个请求,消费者发送JWT
  • 应用验证JWT并根据有效性允许或拒绝用户

刷新令牌流程

  • 用户登录并获得带有自定义声明的JWT以及带有过期日期的刷新令牌
  • 对于每个请求,消费者发送JWT,刷新令牌被扩展并得到更晚的过期日期
  • 如果JWT过期,消费者发送刷新令牌
  • 应用检查刷新令牌是否过期
  • 如果刷新令牌未过期,则颁发JWT并扩展刷新令牌

特性

  • 多个JWT配置文件。每个配置文件都可以有自己的过期时间、密钥等...
  • 生成带有自定义声明的JWT
  • 在生成时可以包含/覆盖公共声明
  • 验证JWT
  • JWT过期配置
  • JWT过期后的刷新令牌流
  • 每次应用程序使用时都扩展刷新令牌,以便用户不会注销
  • 将用户列入黑名单,以便令牌不会被刷新
  • 认证守卫以认证用户

需求

安装

您可以使用Composer在现有的Laravel项目上安装此包

 $ composer require aliirfaan/laravel-simple-jwt

通过编辑 config/app.php 文件并添加到提供者数组中注册ServiceProvider

  aliirfaan\LaravelSimpleJwt\SimpleJwtServiceProvider::class,

注意:对于Laravel <5.1版本,请使用以下内容

 'aliirfaan\LaravelSimpleJwt\SimpleJwtServiceProvider',

使用以下内容发布文件

 $ php artisan vendor:publish --provider="aliirfaan\LaravelSimpleJwt\SimpleJwtServiceProvider"

或者仅使用 php artisan vendor:publish 并从输出列表中选择 aliirfaan\LaravelSimpleJwt\SimpleJwtServiceProvider

应用迁移

 $ php artisan migrate

配置

此包在您的应用程序的 config 文件夹中发布了一个名为 simple-jwt.php 的文件,其中包含此包的设置。大多数变量都绑定到环境变量,但您可以直接编辑此文件或将其配置键添加到 .env 文件。

配置封装在名为“profiles”的数组中,并提供了“default”配置文件。您可以通过添加新的数组键来添加新的配置文件。

jwt_secret | String 用于编码JWT的密钥。您可以使用在线服务(https://mkjwk.org/)或包生成一个。

'jwt_secret' => env('JWT_SECRET')

jwt_algo | String 支持的哈希算法名称

'jwt_algo' => env('JWT_ALGO', 'HS256')

jwt_issuer | String 发行JWT的机构名称,通常是应用程序名称

'jwt_issuer' => env('JWT_ISSUER', config('app.name'))

jwt_audience | String 将接受声明的资源服务器名称,通常是应用程序URL

'jwt_audience' => env('JWT_AUDIENCE', config('app.url'))

jwt_does_expire | Bool (true或false) JWT是否过期

'jwt_does_expire' => env('JWT_DOES_EXPIRE', true)

jwt_ttl_seconds | Numeric 如果jwt_does_expire设置为true,则JWT在多少秒后过期

'jwt_ttl_seconds' => env('JWT_TTL_SECONDS', 900)

jwt_leeway_seconds | Numeric 在检查nbf、iat或过期时间时,我们希望提供一些额外的容错时间以考虑时钟偏移

'jwt_leeway_seconds' => env('JWT_LEEWAY_SECONDS', 0)

jwt_refresh_should_extend | Bool (true或false) 我们是否应该自动扩展JWT刷新令牌

'jwt_refresh_should_extend' => env('JWT_REFRESH_SHOULD_EXTEND', true)

jwt_refresh_ttl_days | Numeric 扩展刷新令牌过期时间的天数

'jwt_refresh_ttl_days' => env('JWT_REFRESH_TTL_DAYS', 90)

使用

新建配置文件

<?php
// simple-jwt.php

'profiles' => [
    // default jwt settings, you can add other profiles with the same format below
    'default' => [
        'jwt_secret' => env('DEFAULT_JWT_SECRET'),
        'jwt_algo' => env('DEFAULT_JWT_ALGO', 'HS256'),
        'jwt_issuer' => env('DEFAULT_JWT_ISSUER', config('app.name')),
        'jwt_audience' => env('DEFAULT_JWT_AUDIENCE', config('app.url')),
        'jwt_does_expire' => env('DEFAULT_JWT_DOES_EXPIRE', true),
        'jwt_ttl_seconds' => env('DEFAULT_JWT_TTL_SECONDS', 900),
        'jwt_leeway_seconds' => env('DEFAULT_JWT_LEEWAY_SECONDS', 0),
        'jwt_refresh_should_extend' => env('DEFAULT_JWT_REFRESH_SHOULD_EXTEND', true),
        'jwt_refresh_ttl_days' => env('DEFAULT_JWT_REFRESH_TTL_DAYS', 90),
    ],
    'custom_profile' => [
        'jwt_secret' => env('CUSTOM_PROFILE_JWT_SECRET'),
        'jwt_algo' => env('CUSTOM_PROFILE_JWT_ALGO', 'HS256'),
        'jwt_issuer' => env('CUSTOM_PROFILE_JWT_ISSUER', config('app.name')),
        'jwt_audience' => env('CUSTOM_PROFILE_JWT_AUDIENCE', config('app.url')),
        'jwt_does_expire' => env('CUSTOM_PROFILE_JWT_DOES_EXPIRE', true),
        'jwt_ttl_seconds' => env('CUSTOM_PROFILE_JWT_TTL_SECONDS', 900),
        'jwt_leeway_seconds' => env('CUSTOM_PROFILE_JWT_LEEWAY_SECONDS', 0),
        'jwt_refresh_should_extend' => env('CUSTOM_PROFILE_JWT_REFRESH_SHOULD_EXTEND', true),
        'jwt_refresh_ttl_days' => env('CUSTOM_PROFILE_JWT_REFRESH_TTL_DAYS', 90),
    ]
]
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use aliirfaan\LaravelSimpleJwt\Services\JwtHelperService; // jwt helper service

class JwtTestController extends Controller
{
     /**
     * Include our service using dependency injection
     */
    public function index(Request $request, JwtHelperService $jwtHelperService)
    {
        // jwt flow

        // payload
        $tokenPayload = array(
            'customer_id' => 1234,
        );

        // include or override claims if needed
        // useful for including project specific claims like scope, locale, nbf, etc...
        // https://www.iana.org/assignments/jwt/jwt.xhtml
        $overrideClaims = array(
            'iss' => 'custom_flow_issuer',
            'iat' => time() + 3000
        );

        // jwt token
        $profile = 'default';
        $jwt = $jwtHelperService->createJwtToken($tokenPayload, $profile, $overrideClaims);
        dd($jwt);

        // verify jwt, you will normally do this in a middleware
        $token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJMYXJhdmVsX2Jsb2ciLCJhdWQiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2Jsb2ciLCJpYXQiOjE2MTIxODAyMTEsImRhdGEiOnsiY3VzdG9tZXJfaWQiOjEyMzR9LCJleHAiOjE2MTIxODExMTF9.uqFln2iQVRvaYvKDTGEG29SrT1flj9JEvFBg2zO3whM';
        $verifyJwt = $jwtHelperService->verifyJwtToken($token);
        if ($verifyJwt['errors'] == true) {

        } else {
            //get your token claims
            $tokenClaims = (array) $verifyJwt['result'];
            //dd($tokenClaims);
        }

        // refresh token flow. Using refresh flow is optional and depends on your use case
        
        $modelType = 'customer'; // your model type name you want, should be unique so that you can sent refresh tokens to multiple types of model 
        $modelId = 253; // your model id
        $refreshToken = '798798-543543-5435432543'; // the refresh token sent by consumer/client, will be null for new logins
        $deviceId = 1536-452; // your device id if you are using devic_id column

        $refreshTokenResult = processRefreshToken($modelType, $modelId, $refreshToken, $deviceId);
        dd($refreshTokenResult);
    }
}

中间件使用

您可以在路由中间件中验证jwt,如下所示。请勿忘记注册您的中间件。

<?php

namespace App\Http\Middleware;

use Closure;
use aliirfaan\LaravelSimpleJwt\Services\JwtHelperService;

class SimpleJwtVerifyExample
{
    protected $jwtServiceInstance;

    public function __construct(JwtHelperService $jwtHelperService)
    {
        $this->jwtHelperService = $jwtHelperService;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        try {

            // get token from header bearer token
            $token = $request->bearerToken();
            
            $verifyToken = $this->jwtHelperService->verifyJwtToken($token);
            if ($verifyToken['errors'] == true) {

            }

            // passed token validate, continue with request
            $tokenClaims = (array) $verifyToken['result'];
            $request->attributes->add(['token_claims' => $tokenClaims]);

        } catch (\Exception $e) {
            //
        }

        return $next($request);
    }
}

守卫器使用

要使用守卫器,请将其添加到您的认证配置中

config\auth.php
    'guards' => [
        'api' => [
            'driver' => 'simple-jwt-guard',
            'provider' => 'user',
            'profile' => 'default', // the jwt profile you want to use for the provider
            'jwt_class' => null // if you have implemented your own jwt service that implements JwtServiceInterface
        ]
    ],

许可证

MIT许可证(MIT)

版权所有(c)2020

在此特此免费许可任何人获得本软件及其相关文档副本(以下简称“软件”),在不限制的情况下使用软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本,以及允许向提供软件的人士使用软件,前提是必须遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

本软件按“现状”提供,不提供任何形式的保证,无论是明示的、暗示的还是其他形式的保证,包括但不限于适销性、特定用途的适用性和非侵权性。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是由合同、侵权或其他原因引起的,无论是与软件、软件的使用或其他方式相关的。