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
相关产品推荐
相关产品推荐

