碰到诡异 Redis 的问题,请大神指教一二

我最近用laravel 7.13.0起了一个项目,在项目里的api模块,自己实现了jwt的登陆验证功能,但是很诡异的是我这边Redis出了问题。

说一下我遇到的问题

我现在登陆功能是没有问题,也能往redis里写数据,但是同一个控制器的logout就有问题,因为中间件的缘故,会提示“请重新登陆”。我在login的方法里执行
print_r(Redis::get('*'));exit;能打印出我登陆用户的key,但是我在中间件里执行相同的语句却什么也打印不出来,继而无法做token验证,没有任何的报错,try catch捕获不到任何异常,诡异至极。

我尝试着在中间件里压入一些值,然后再取出来,是没问题的,但是我在login方法里却看不到那些key和值,更加诡异的是我进入服务器redis-cli里也找不到在中间件里存的值,redis15个库我全keys *,就是没有,然后中间件里的值还是真实存在的。我是完全没有头绪了。

上代码

route

Route::group(['middleware'=>'checktoken'],function (){
    Route::post('/logout','\App\Http\Controllers\Api\DriversController@logout');
    Route::post('/addplan','\App\Http\Controllers\Api\PlansController@addPlan');
    Route::post('/endplan','\App\Http\Controllers\Api\PlansController@endPlan');
});

Route::post('/login','\App\Http\Controllers\Api\DriversController@login');

config/database.php

...
'redis' => [

  'client' => env('REDIS_CLIENT', 'predis'),

//        'options' => [
//            'cluster' => env('REDIS_CLUSTER', 'redis'),
//            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
//        ],

  'default' => [
//            'url' => env('REDIS_URL'),
  'host' => env('REDIS_HOST', '127.0.0.1'),
  'password' => env('REDIS_PASSWORD', null),
  'port' => env('REDIS_PORT', '6379'),
  'database' => env('REDIS_DB', '0'),
 ],
  'cache' => [
//            'url' => env('REDIS_URL'),
  'host' => env('REDIS_HOST', '127.0.0.1'),
  'password' => env('REDIS_PASSWORD', null),
  'port' => env('REDIS_PORT', '6379'),
  'database' => env('REDIS_CACHE_DB', '1'),
 ],
 ],

middleware

public function handle($request, Closure $next)
    {
        $token = $request->header('token');
        $uid = $request->header('uid');

        $cache = Redis::get('D:U:'.$uid);
        if(!$cache){
            return \response('请重新登陆',301);
        }
        if($token != $cache){
            return \response('请重新登陆',301);
        }
        JWT::$leeway = 60;
        $alg =
            [
                "typ" => "JWT", //声明类型为jwt
                "alg" => "HS256" //声明签名算法为SHA256
            ];
        $key = 'FrNc-TAbK29_HwbQK_tM';
        try{
            JWT::decode($token,$key,$alg);
        }
        catch (\Exception $e) {
            return response()->json('token无效:' . $e);
        }

        return $next($request);
    }

控制器

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Driver;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use \Firebase\JWT\JWT;
use Illuminate\Support\Facades\Redis;

class DriversController extends Controller
{

    public function __construct()
    {
        $this->middleware('checktoken', ['except' => ['login']]);
    }

    /**
     * 登陆
     * @param Request $request
     * @return array|\Illuminate\Http\JsonResponse
     */
    public function login(Request $request){
        $post = $request->post();
        //验证
        $rules = [
            'phone' => 'required|regex:/^1[34578]\d{9}$/',
            'password' => 'required|min:8',
        ];
        $messages = [
            'phone.required' => '手机号不能为空',
            'phone.phone' => '手机号无效',
            'password.required' => '密码不能为空',
            'password.min' => '密码长度不能少于8个字符',
        ];
        $validator = Validator::make($post, $rules, $messages);
        if ($validator->fails()) {
            return response()->json(['code' => 0, 'msg' => '数据校验失败', 'data' => $validator->errors()->all()]);
        }
        $driver = Driver::with(['groups','companies'])->where('phone',$post['phone'])->first()->toArray();
        if(empty($driver)){
            return response()->json(['code' => 0, 'msg' => '手机号码或密码错误', 'data' => []]);
        }
        if(!Hash::check($post['password'],$driver['password'])){
            return response()->json(['code' => 0, 'msg' => '手机号码或密码错误', 'data' => []]);
        }
        $driver['company_name'] = $driver['companies']['name'];
        $driver['group_name'] = $driver['groups']['name'];
        unset($driver['password']);
        unset($driver['companies']);
        unset($driver['groups']);
        if(!$token = Redis::get('D:U:'.$driver['id'])){
            if(!$token = $this->getJWTToken($driver)){
                return response()->json(['code'=>0,'msg'=>'未知错误']);
            }
            Redis::set('D:U:'.$driver['id'], $token);
            Redis::expire('D:U:'.$driver['id'],72000);
        }

        $result = [
            'userInfo' => $driver,
            'token' => $token
        ];
        return response()->json(['code'=>1, 'msg'=>'登陆成功','data'=>$result]);
    }

    public function logout(Request $request){
        $uid = $request->header('uid');
        Redis::del('D:U:'.$uid);
        return response()->json(['code'=>1, 'msg'=>'登出成功', 'data'=>[]]);
    }

    private function getJWTToken($value)
    {
        $time = time();
        $payload = [
            'iat' => $time,
            'nbf' => $time,
            'exp' => $time + 7200,
            'data' => [
                'userInfo' => $value['id']
            ]
        ];
        $key = 'FrNc-TAbK29_HwbQK_tM';
        $alg = 'HS256';
        $token = JWT::encode($payload, $key, $alg);
        return $token;

    }
}

我想请问一下大神们,在middleware里用redis会出现这种情况吗?请问有没有解决办法或者思路呢?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

代码没有问题,首先检查配置,你要明白Redis::set 操作以后只要设置的key没有过期,肯定是可以get到的,如果不能get到说明key是不存在的。第二你使用laravel 框架没必要手动实现jwt 我看你引入的包像是为tp开发的,使用laravel 的话强烈推荐composer reuqire tymon/jwt-auth 这是文档,博客:JWT 完整使用详解

3年前 评论
qingningba (楼主) 3年前
pan_zoe (作者) 3年前
讨论数量: 2

没有大神遇到过这种问题吗?

3年前 评论

代码没有问题,首先检查配置,你要明白Redis::set 操作以后只要设置的key没有过期,肯定是可以get到的,如果不能get到说明key是不存在的。第二你使用laravel 框架没必要手动实现jwt 我看你引入的包像是为tp开发的,使用laravel 的话强烈推荐composer reuqire tymon/jwt-auth 这是文档,博客:JWT 完整使用详解

3年前 评论
qingningba (楼主) 3年前
pan_zoe (作者) 3年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!