Laravel中如何使用API返回的响应密钥作为中间件实现路由鉴权
全路由API令牌鉴权实现方案
你之前用中间件做登录态校验的思路完全可以复用,只是把本地session校验逻辑替换为API令牌校验即可,具体实现分4步:
1. 改造登录流程,安全存储返回令牌
你当前的Basic Auth登录请求逻辑不需要改,拿到接口响应后先解析出返回的鉴权令牌,用安全的方式存储:
- 优先用
httpOnly属性的Cookie存储令牌,禁止前端JS直接读取,避免XSS攻击窃取;同时开启secure(HTTPS环境)、SameSite=Strict属性防止CSRF风险 - 不要把令牌存在localStorage、sessionStorage这类可被JS读取的存储中
PHP示例代码:
// 解析登录接口返回结果,字段名替换成你接口实际返回的字段即可 $responseData = json_decode($response->getBody()->getContents(), true); $authToken = $responseData['access_token']; $expireTs = time() + $responseData['expires_in']; // 接口一般会返回令牌有效时长,单位为秒 // 写入安全Cookie setcookie( name: 'api_auth_token', value: $authToken, expire: $expireTs, path: '/', secure: true, httponly: true, samesite: 'Strict' );
2. 开发全局鉴权中间件
中间件逻辑分三层,和你之前做本地登录校验的流程基本一致:
- 先配置白名单:登录页、登录提交接口、公开访问的静态资源、回调地址等不需要鉴权的路径直接放行,避免重定向死循环
- 校验请求携带的Cookie中是否存在有效令牌,不存在直接重定向到登录页
- 携带令牌请求后端API的令牌校验接口(一般是
/me、/token/check这类校验端点,按你后端API实际提供的地址配置):- 接口返回200状态码代表令牌有效,把接口返回的用户信息挂载到请求对象上,放行请求到对应业务路由
- 接口返回401/403状态码代表令牌过期、伪造或被吊销,清除本地无效Cookie,重定向到登录页
- 接口请求超时或服务异常时,返回503兜底提示页
以PHP PSR规范中间件为例(适配Laravel、Slim、Hyperf等主流PHP框架):
<?php namespace App\Http\Middleware; use GuzzleHttp\Client; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as Handler; use Psr\Http\Message\ResponseInterface as Response; class ApiAuthMiddleware { public function process(Request $request, Handler $handler): Response { // 白名单路由直接放行 $currentPath = $request->getUri()->getPath(); $publicPaths = ['/login', '/api/sign-in', '/favicon.ico']; if (in_array($currentPath, $publicPaths)) { return $handler->handle($request); } // 检查Cookie中是否存在令牌 $token = $request->getCookieParams()['api_auth_token'] ?? ''; if (empty($token)) { return new \GuzzleHttp\Psr7\Response(302, ['Location' => '/login']); } // 请求后端API校验令牌有效性 try { $client = new Client(); $checkResp = $client->get('你的API令牌校验地址', [ 'headers' => [ // 令牌前缀按后端API要求调整,多数场景为Bearer 'Authorization' => 'Bearer ' . $token, 'Accept' => 'application/json' ], 'timeout' => 3 ]); // 校验通过,写入用户信息到请求属性,后续业务可直接调用 $user = json_decode($checkResp->getBody()->getContents(), true); $request = $request->withAttribute('current_user', $user); return $handler->handle($request); } catch (\GuzzleHttp\Exception\ClientException $e) { // 令牌无效,清除过期Cookie跳登录 setcookie('api_auth_token', '', time() - 3600, '/'); return new \GuzzleHttp\Psr7\Response(302, ['Location' => '/login?code=invalid_token']); } catch (\Exception $e) { // 鉴权服务异常兜底 return new \GuzzleHttp\Psr7\Response(503, [], '服务暂时不可用,请稍后重试'); } } }
3. 注册中间件为全局路由中间件
把写好的鉴权中间件注册到框架的全局中间件栈中,默认覆盖所有Web路由,不需要单独给路由分组加鉴权注解,避免后续新增路由漏加鉴权导致未授权访问。
如果你用的是React/Vue这类纯前端SPA应用,逻辑完全一致:把服务端中间件替换成前端路由守卫,令牌同样存在httpOnly Cookie中,路由跳转前调用校验接口判断是否放行即可,所有API请求统一配置携带Cookie。
4. 业务请求统一附带令牌
后续所有业务逻辑调用后端API时,直接从Cookie中读取存储的令牌,放到请求的Authorization头中传给后端即可,不需要在每个业务接口重复做登录态校验。如果后端API提供了令牌刷新接口,可以在中间件校验时判断令牌剩余有效期,临近过期时自动调用刷新接口更新Cookie中的令牌,避免用户频繁掉线。
额外优化点
- 静态资源(JS/CSS/图片等)可以直接在Nginx/Apache层面配置放行,不需要走中间件鉴权逻辑,减少不必要的API请求,提升响应速度
- 可以在中间件层做短时间的本地缓存(比如1分钟Redis缓存),把令牌和对应的用户信息做映射,避免每个请求都调用后端校验接口,降低后端API压力
- 登出逻辑直接清除本地存储的Cookie,同时调用后端API的令牌吊销接口即可
内容的提问来源于stack exchange,提问作者Catto
相关产品推荐
相关产品推荐

