You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中Guzzle调用API携带Token认证返回401问题排查

问题根因
  • 硬编码的JWT Token已过期:解码你提供的Token payload可见,exp过期时间戳为1656383141,和签发时间iat1656383111仅间隔30秒,这类短有效期Token硬编码后,等你发起成本查询请求时早已失效,后端自然返回未登录响应。
  • GET请求传参方式错误:Guzzle中form_params仅用于POST/PUT等请求发送表单格式请求体,GET请求的查询参数需要放在query选项下。你把分页参数放在form_params中,一方面参数不会被拼接到URL上,另一方面部分API网关/服务会直接拒绝携带请求体的GET请求,导致请求根本没到达业务鉴权逻辑。
  • 登录请求头配置不规范:你当前的登录方法把Authorization头直接放在请求选项根级,没有放入headers数组内,现在能登录成功完全是后端兼容了form_params中传递的账号密码,属于歪打正着,这类不规范写法在其他接口上会直接导致头信息丢失。
修复方案
  1. 修正登录方法的头配置,拿到Token后禁止硬编码,存储到Laravel的Session/Cache中;每次调用业务接口前先判断Token是否过期,过期就用返回的refreshToken调用刷新接口获取新Token,不要用固定的过期Token调试。
    修正后的登录方法参考:
    public function login($user_id, $password)
    {
        try {
            $guzzle = new Client();
            $url = config('app.base_api_url') . 'auth/signin';
            $credentials = base64_encode($user_id.':'.$password);
    
            $response = $guzzle->post($url, [
                // 头信息统一放在headers数组下
                'headers' => [
                    'Authorization' => 'Basic '.$credentials,
                ],
                'form_params' => [
                    'userid' => $user_id,
                    'password' => $password,
                ],
            ]);
            $result = json_decode($response->getBody(), true);
            // 把token、refreshToken存储到session,不要硬编码
            session([
                'api_token' => $result['user']['payload']['token'],
                'api_refresh_token' => $result['user']['payload']['refreshToken'],
            ]);
            return $result;
        } catch (\Exception $e) {
            throw $e;
        }
    }
    
  2. 修正成本查询接口的参数传递方式,GET请求参数改用query选项,Token动态从存储中读取,不要硬编码:
    public function getCost($page, $order_dir, $limit)
    {
        try {
            $guzzle = new Client();
            $url = config('app.base_api_url') . 'api/v1/costs';
            // 动态从session取token,此处可增加过期判断逻辑,过期先刷新token再发起请求
            $token = session('api_token');
    
            $response = $guzzle->get($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $token,
                ],
                // GET请求参数用query,不要用form_params
                'query' => [
                    'page' => $page,
                    'order_dir' => $order_dir,
                    'limit' => $limit,
                ],
                // 调试阶段可开启debug,打印实际请求内容排查问题
                // 'debug' => true
            ]);
    
            return json_decode($response->getBody());
        } catch (\Exception $e) {
            throw $e;
        }
    }
    
  3. 调整后如果仍返回401,开启Guzzle的debug选项,确认实际发出的请求里Authorization头正常携带、格式为Bearer 有效未过期token,没有被中间件过滤即可。不需要额外执行手动登录操作,只要请求携带的Token格式正确且在有效期内,就能正常通过鉴权。

内容的提问来源于stack exchange,提问作者Catto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:19:52