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

Laravel OAuth2密码模式登录请求超时(cURL error 28)求助

Laravel OAuth2密码模式请求token端点出现cURL error 28超时的解决方案

问题描述

我正在开发集成OAuth2认证的Laravel应用,采用密码授权模式登录获取access token时,请求token端点遭遇cURL error 28超时错误。

登录接口代码如下:

public function login(LoginRequest $request)
{
    $customer = Customer::where('username', $request->username)->first();

    $oClient = OClient::where('password_client', 1)->first();
    if (!$oClient) {
        return response()->json([
            'status' => 'failed',
            'message' => 'OAuth client not found',
            'code' => 400
        ], 400);
    }

    $response = Http::asForm()->post('http://localhost:8000/oauth/token', [
        'grant_type' => 'password',
        'client_id' => $oClient->id,
        'client_secret' => $oClient->secret,
        'username' => $request->username,
        'password' => $request->password,
        'provider' => 'customers',
        'scope' => '*',
    ]);

    if ($response->successful()) {
        $tokens = $response->json();
        return response()->json([
            'access_token' => $tokens['access_token'],
            'refresh_token' => $tokens['refresh_token'],
        ]);
    } else {
        return response()->json([
            'status' => 'failed',
            'message' => $response->json('error_description', 'Unknown error'),
            'code' => $response->status(),
        ], $response->status());
    }
}

通过Postman测试API时返回错误:

{
  "status": "failed",
  "message": "cURL error 28: Operation timed out after 30016 milliseconds with 0 bytes received for http://localhost:8000/oauth/token",
  "code": 400
}

解决方案

1. 避免本地请求死锁(最常见原因)

在Laravel应用内部通过Http客户端请求同应用的本地端点时,会因PHP-FPM进程阻塞导致超时——当前请求等待内部请求完成,但内部请求需要新进程处理,进程池已满就会卡死。

解决方法:直接使用应用内部调用生成令牌,无需走HTTP请求:

use Illuminate\Support\Facades\Hash;

public function login(LoginRequest $request)
{
    $customer = Customer::where('username', $request->username)->first();
    
    // 先验证用户密码
    if (!$customer || !Hash::check($request->password, $customer->password)) {
        return response()->json([
            'status' => 'failed',
            'message' => 'Invalid credentials',
            'code' => 401
        ], 401);
    }

    $oClient = OClient::where('password_client', 1)->first();
    if (!$oClient) {
        return response()->json([
            'status' => 'failed',
            'message' => 'OAuth client not found',
            'code' => 400
        ], 400);
    }

    // 直接生成令牌(需确保Customer模型已使用HasApiTokens trait)
    $tokenResult = $customer->createToken('Customer Login Token', ['*']);
    
    return response()->json([
        'access_token' => $tokenResult->accessToken,
        'refresh_token' => $tokenResult->refreshToken,
    ]);
}

2. 调整本地域名解析

如果必须使用HTTP请求,将localhost替换为127.0.0.1(避免IPv6解析问题):

$response = Http::asForm()->post('http://127.0.0.1:8000/oauth/token', [
    'grant_type' => 'password',
    'client_id' => $oClient->id,
    'client_secret' => $oClient->secret,
    'username' => $request->username,
    'password' => $request->password,
    'provider' => 'customers',
    'scope' => '*',
]);

容器化部署的场景,改用容器内部域名(比如http://laravel-app:8000)。

3. 检查PHP-FPM进程配置

若使用PHP-FPM,确保pm.max_children、pm.start_servers参数足够,避免进程耗尽导致请求阻塞。修改对应配置文件后重启PHP-FPM服务。

4. 临时调整超时时间(仅应急)

如果是临时网络波动导致的超时,可临时延长Http客户端超时时间:

$response = Http::asForm()->timeout(60)->post('http://localhost:8000/oauth/token', [...]);

5. 验证端点可用性

直接在Postman中手动发送POST请求到http://localhost:8000/oauth/token,确认端点本身是否能正常响应,排除端点配置错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:13:13