tp5 JWT生成token验证接口安全、防止高频请求

1.composer安装 jwt

composer require lcobucci/jwt 3.3

2.在extend/tools/jwt目录下创建Token.php文件

注意 extend目录下tools/jwt目录没有需要自己创建

<?php
 
namespace tools\jwt;
 
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;
 
class Token
{   
    // createToken为生成token令牌的方法
    public static function createToken($uid = null)
    {
        $signer = new Sha256();//加密规则
        $time = time();//当前时间
 
        $token = (new Builder())
            ->issuedBy('teacher')//签发人
            ->canOnlyBeUsedBy('student')//接收人
            ->identifiedBy('MarsLei', true) //标题id
            ->issuedAt($time)//发出令牌的时间
            ->canOnlyBeUsedAfter($time) //生效时间(即时生效)
            ->expiresAt($time + 3600) //过期时间
            ->with('uid', $uid) //用户id
            ->sign($signer, 'my') //签名
            ->getToken(); //得到token
        return (string)$token;
    }
    //verifyToken 为验证token令牌的方法
    public static function verifyToken($token=null){
        //检测是否接收到了token
        if(empty($token)){
            return 0;
        }
        //转化为可以验证的token
        $token = (new Parser())->parse((string) $token);
        //验证基本设置
        $data = new ValidationData();
        $data->setIssuer('teacher');
        $data->setAudience('student');
        $data->setId('MarsLei');
 
        if(!$token->validate($data)){
            return 0;
        }
        //验证签名
        $signer = new Sha256();
        if(!$token->verify($signer, 'my')){
            return 0;
        }
        //验证通过,返回用户id
        return $token->getClaim('uid');
    }
 
}

3.生成token 验证token的方法

 一般我们在登录成功后将用户数据的id生成token令牌


//生成token
$token = Token::createToken($userInfo['id']); //生成token
//验证Token
$res = Token::verifyToken($token);
if (!$res) {
   //验证失败
   $this->error('token令牌失效', 'home/Login/login');

}

4.在controller目录下创建Base控制器

  让你需要验证的控制器继承Base控制器

<?php

namespace app\home\controller;

use think\Cache;
use think\Controller;
use think\Request;
use think\Session;
use tools\jwt\Token;

class Base extends Controller
{    
    //将你控制器中不需要验证的方法写在此数组中即可不用token验证
    protected $url = ['book/book',"book/type","book/detail"];

    function __construct(Request $request = null)
    {
        $ip = request()->ip();//获取ip地址
        $num = Cache::store('redis')->get($ip.'times');//获取请求次数
        $lastTime =Cache::store('redis')->get($ip);//获取上次请求的时间
        if(time()-$lastTime<60)
        {
//            echo $num;
            if ($num >=5)//每分钟请求大于等于5次的时候限制请求
            {
                $res = [
                    'code' => 511,
                    'msg' => '操作过于频繁,'
                ];
                echo json($res)->send();die;//返回信息阻止继续请求

            }
        }
        if($num>=5){
            Cache::store('redis')->handler()->del($ip.'times');//等待时间过期后清除单位时间请求次数
        }
         parent::__construct($request);
         $route = strtolower(request()->controller().'/'.request()->action());//获取请求控制器和方法
         if(!in_array($route,$this->url))//判断请求的控制器方法是否在数组中,没有则需要登录验证
         {
                   $token = request()->param('token');
                    if (empty($token))
                    {
                        $this->fail('token不存在', 403);die;//fail()是封装好的方法
                    }
                    //令牌验证
                    $res = Token::verifyToken($token);
                    if (!$res)
                    {
                        $this->fail('token无效',500);die;
                    }
         }
         Cache::store('redis')->set($ip,time());//将同一ip地址的第一次请求时间存入缓存
         Cache::store('redis')->inc($ip.'times');//请求次数存入Redis做自增
    }


    protected function response($code=200, $msg='success', $data=[])
    {
        $res = [
            'code' => $code,
            'msg' => $msg,
            'data' => $data
        ];
        //原生php写法
//        echo json_encode($res, JSON_UNESCAPED_UNICODE);die;
        //框架写法
        json($res)->send();

    }
    /**
     * 成功的响应
     * @param array $data 返回数据
     * @param int $code 错误码
     * @param string $msg 错误信息
     */
    protected function ok($data=[], $code=200, $msg='success')
    {
        $this->response($code, $msg, $data);
    }

    /**
     * 失败的响应
     * @param $msg 错误信息
     * @param int $code 错误码
     * @param array $data 返回数据
     */
    protected function fail($msg, $code=500, $data=[])
    {
        $this->response($code, $msg, $data);
    }

}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值