TP6 JWT Token 生成 控制器使用 中间件使用

0x01

建议使用composer安装 方便 快捷

composer require firebase/php-jwt

0x02 引入JWT类(common.php 公共文件)

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\BeforeValidException;

0x03        生成token (common.php文件中)

/**
 * 生成token
 * $uid 输入用户openid&&id
 */

if (!function_exists('signToken')) {
	//生成验签
	function signToken($uid)
	{
		$key = '!@#$%*&';         //这里是自定义的一个随机字串,应该写在config文件中的,解密时也会用,相当    于加密中常用的 盐  salt
		$token = array(
			"iss" => '',         	//签发者 可以为空
			"aud" => '',         	//面象的用户,可以为空
			"iat" => time(),      	//签发时间
			"nbf" => time() + 3,      	//在什么时候jwt开始生效  (这里表示生成100秒后才生效)
			"exp" => time() + 2000, //token 过期时间
			'data' => $uid			//记录的userid的信息,这里是自已添加上去的,如果有其它信息,可以再添加数组的键值对
		);
		$jwt = JWT::encode($token, $key, "HS256");  //根据参数生成了 token
		return $jwt;
	}
}

0x04        验证token(common.php文件中)

/**
 * 验证token
 * $token 生成的token值
 */

if (!function_exists('checkToken')) {
	//验证token
	function checkToken($token)
	{
		$key = '!@#$%*&';
		$status = array("code" => 2);

		try {
			JWT::$leeway = 60; //当前时间减去60,把时间留点余地
			$decoded = JWT::decode($token, new Key($key, 'HS256')); //HS256方式,这里要和签发的时候对应
			$arr = (array)$decoded;
			$res['code'] = 1;
			$res['data'] = $arr['data'];
			return $res;
		} catch (SignatureInvalidException $e) { //签名不正确
			$status['msg'] = "签名不正确";
			return $status;
		} catch (BeforeValidException $e) { // 签名在某个时间点之后才能用
			$status['msg'] = "token未生效";
			return $status;
		} catch (ExpiredException $e) { // token过期
			$status['msg'] = "token失效";
			return $status;
		} catch (Exception $e) { //其他错误
			$status['msg'] = "未知错误";
			return $status;
		}
	}
}

0x05        控制器中使用生成

        $openid = 'ajshdkljahskjdhajk';
        return showSuccess(signToken($openid));

0x06        控制器中使用验证

        $token = Request::instance()->header('token');
        $res = checkToken($token);
        return showSuccess($res);

0x07        中间件中使用

通过命令行指令快速生成中间件

php think make:middleware Check

这个指令会 app/middleware目录下面生成一个Check中间件。

<?php

namespace app\middleware;

class Check
{
    public function handle($request, \Closure $next)
    {
        if ($request->param('name') == 'think') {
            return redirect('index/think');
        }

        return $next($request);
    }
}

中间件的入口执行方法必须是handle方法,而且第一个参数是Request对象,第二个参数是一个闭包。

修改上面这个文件app/middleware/CheckToken.php

<?php
 
declare(strict_types=1);
 
namespace app\middleware;
 
// 数据库
use app\model\Admins;
 
class CheckToken
{
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        // 获取token
        $token = $request->header('token');
        // 验证是否存在token
        if (empty($token)) {
            return json(['msg' => 'error', 'data' => 'token为空']);
        } else {
            $admins_token =  Admins::where('token', $token)->find();
            // JWT进行校验token
            $res = checkToken($token);
            // token是否存在数据库中
            if (empty($admins_token)) {
                return json(['msg' => 'error', 'data' => 'token不合法']);
                // token是否正确
                if ($res['code'] != 1) {
                    return json(['msg' => 'error', 'data' => 'token验证失败']);
                }
            }
        }
 
        return $next($request); //返回请求数据本身
    }
}

控制器中间件使用        ['except' => 'login']] 可以剔除不需要验证token的函数

    protected $middleware = [\app\middleware\CheckToken::class => ['except' => 'login']];

如果全局应用验证token中间件

在\app\middleware.php文件中添加

<?php
// 全局中间件定义文件
return [
    // 全局请求缓存
    // \think\middleware\CheckRequestCache::class,
    // 多语言加载
    // \think\middleware\LoadLangPack::class,
    // Session初始化
    // \think\middleware\SessionInit::class
    // 注册中间件
    \app\middleware\Check::class
    // 跨域
    // \think\middleware\AllowCrossDomain::class
];

猜你喜欢

转载自blog.csdn.net/qq_43929048/article/details/123504563