Laravel 8集成JWT Auth调用logout API出现SSL连接错误
我是Laravel框架下JWT认证方案的新手开发者,当前正在开发个人管理应用,技术栈选型如下:
- 后端:Laravel 8框架
- 前端:React框架
- 身份认证能力:基于JWT Token实现
Laravel端项目已按照参考教程完成全部配置。
对接React前端API前,我先使用Insomnia工具开展接口测试:目前其余API均可正常响应,自定义业务接口也可正常从数据库查询返回数据,但调用POST请求的logout接口(请求地址:https://localhost:8000/api/logout)时,返回错误信息:"Error: SSL connect error",暂未定位问题成因,现将相关代码附在下方,需要排查建议与解决方案。
JWT控制器代码
<?php namespace App\Http\Controllers; use Auth; use Validator; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; class JWTController extends Controller { /** * Create a new AuthController instance. * * @return void */ public function __construct() { $this->middleware('auth:api', ['except' => ['login', 'register']]); } /** * Register user. * * @return \Illuminate\Http\JsonResponse */ public function register(Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|string|min:2|max:100', 'email' => 'required|string|email|max:100|unique:users', 'password' => 'required|string|confirmed|min:6', ]); if($validator->fails()) { return response()->json($validator->errors(), 400); } $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password) ]); return response()->json([ 'message' => 'User successfully registered', 'user' => $user ], 201); } /** * login user * * @return \Illuminate\Http\JsonResponse */ public function login(Request $request) { $validator = Validator::make($request->all(), [ 'email' => 'required|email', 'password' => 'required|string|min:6', ]); if ($validator->fails()) { return response()->json($validator->errors(), 422); } if (!$token = auth()->attempt($validator->validated())) { return response()->json(['error' => 'Unauthorized'], 401); } return $this->respondWithToken($token); } /** * Logout user * * @return \Illuminate\Http\JsonResponse */ public function logout() { auth()->logout(true); return response()->json(['message' => 'User successfully logged out.']); } /** * Refresh token. * * @return \Illuminate\Http\JsonResponse */ public function refresh() { return $this->respondWithToken(auth()->refresh()); } /** * Get user profile. * * @return \Illuminate\Http\JsonResponse */ public function profile() { return response()->json(auth()->user()); } /** * Get the token array structure. * * @param string $token * * @return \Illuminate\Http\JsonResponse */ protected function respondWithToken($token) { return response()->json([ 'access_token' => $token, 'token_type' => 'bearer', 'expires_in' => auth()->factory()->getTTL() * 60 ]); } }
api.php路由文件代码
<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\JWTController; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ Route::group(['middleware' => ['api', 'cors']], function($router) { Route::post('/register', [JWTController::class, 'register']); Route::post('/login', [JWTController::class, 'login']); Route::post('/logout', [JWTController::class, 'logout']); Route::post('/refresh', [JWTController::class, 'refresh']); Route::post('/profile', [JWTController::class, 'profile']); });
按优先级从高到低逐步排查:
优先排查请求层SSL校验问题(90%概率为该原因)
其余接口正常仅logout报错大概率是偶发的证书信任问题,本地开发用的自签名HTTPS证书默认不被Insomnia信任,会直接拦截连接抛出SSL错误。- 快速验证:把请求地址从
https://localhost:8000/api/logout换成http://localhost:8000/api/logout重试,本地开发环境不需要强制HTTPS,如果能正常响应即可确认是证书问题。 - 永久解决:打开Insomnia设置,找到请求配置分类下的
Validate certificates开关,关闭后重启Insomnia即可正常请求HTTPS地址。
- 快速验证:把请求地址从
排查路由中间件重复加载问题
Laravel的routes/api.php文件默认已经被框架加载在api中间件组下,你在路由组里重复添加api中间件会导致请求生命周期异常,部分场景下会触发意外的HTTPS跳转。
修正路由代码:Route::group(['middleware' => ['cors']], function($router) { Route::post('/register', [JWTController::class, 'register']); Route::post('/login', [JWTController::class, 'login']); Route::post('/logout', [JWTController::class, 'logout']); Route::post('/refresh', [JWTController::class, 'refresh']); Route::post('/profile', [JWTController::class, 'profile']); });排查请求头携带问题
logout接口被auth:api中间件保护,请求时必须携带合法的Authorization: Bearer {你的登录token}请求头,未携带token时如果认证中间件配置错误,会把请求重定向到HTTPS的登录页,触发本地证书的SSL错误。
检查app/Http/Middleware/Authenticate.php的redirectTo方法,确保API请求下不会触发页面跳转:protected function redirectTo($request) { if (! $request->expectsJson()) { return route('login'); } }排查JWT黑名单存储配置
auth()->logout(true)方法会把当前失效的token加入黑名单,默认存储在缓存中,如果本地缓存连接异常,也会抛出异常中断请求。检查.env文件的CACHE配置,确认缓存驱动可用,临时测试可以把CACHE_DRIVER改成array重试。
内容的提问来源于stack exchange,提问作者64Bit1990

