碰到诡异 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会出现这种情况吗?请问有没有解决办法或者思路呢?
代码没有问题,首先检查配置,你要明白Redis::set 操作以后只要设置的key没有过期,肯定是可以get到的,如果不能get到说明key是不存在的。第二你使用laravel 框架没必要手动实现jwt 我看你引入的包像是为tp开发的,使用laravel 的话强烈推荐composer reuqire tymon/jwt-auth 这是文档,博客:JWT 完整使用详解