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

1.composer安装 jwt

composer require lcobucci/jwt 3.3

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

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

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控制器

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);
    }

}

你可能感兴趣的:(tp5框架,安全)