Laravel项目间Guzzle Digest认证失效,请求返回登录页
Laravel跨项目Guzzle请求认证页面返回登录页的解决方案
咱先捋清楚问题:你有两个Laravel项目,项目一有俩页面——一个得登录认证才能进,另一个随便访问。用项目二的Guzzle请求时,免认证页面正常,但要认证的那个只返回登录页。你当前的Guzzle代码是这样的:
<?php $client = new Client([ 'base_uri' => 'my_base_url', 'timeout' => 5.0, 'auth' => ['login', 'password', 'digest'], 'headers' => array( 'Accept' => 'application/vnd.comay.v1.1+xml', 'Content-Type' => 'text/xml' ), ]); $response = $client->get('/products/page2'); echo $response->getReasonPhrase(); $body = $response->getBody(); echo $body; ?>
问题根源
Laravel默认的认证系统(不管是Breeze、Jetstream还是老UI)都是靠Session/Cookie维持登录状态的,但你现在用的auth参数是HTTP摘要认证,这和Laravel的Session认证完全不是一套逻辑!Guzzle发的请求里没有Laravel认的Session Cookie,系统自然判定你未登录,直接重定向到登录页了。
解决办法
临时方案:带Session Cookie请求
适合快速测试,步骤如下:
- 手动登录项目一,打开浏览器开发者工具(F12),在
Application标签的Cookies里找到Laravel的Session Cookie(默认名叫laravel_session,具体看你项目一.env里的SESSION_COOKIE配置) - 修改Guzzle配置,把这个Cookie加进去:
<?php $client = new Client([ 'base_uri' => 'my_base_url', 'timeout' => 5.0, 'headers' => array( 'Accept' => 'application/vnd.comay.v1.1+xml', 'Content-Type' => 'text/xml', 'Cookie' => 'laravel_session=你复制的cookie值' // 这里加Cookie ), ]); $response = $client->get('/products/page2'); echo $response->getReasonPhrase(); $body = $response->getBody(); echo $body; ?>
推荐方案:用API令牌认证(服务间调用更靠谱)
Session Cookie的方式不仅有效期有限,跨域名还容易出问题,服务间调用更适合用Laravel的API令牌:
- 在项目一安装Laravel Sanctum(轻量够用):
composer require laravel/sanctum php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" php artisan migrate - 在项目一的
User模型里添加HasApiTokenstrait:use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; // ... 其他代码 } - 给需要调用的用户生成API令牌(可以手动在tinker里生成,或者做个后台页面):
php artisan tinker $user = User::where('email', 'login@example.com')->first(); $token = $user->createToken('Project2Access')->plainTextToken; echo $token; // 复制这个令牌 - 修改Guzzle请求,带上Bearer令牌:
<?php $client = new Client([ 'base_uri' => 'my_base_url', 'timeout' => 5.0, 'headers' => array( 'Accept' => 'application/vnd.comay.v1.1+xml', 'Content-Type' => 'text/xml', 'Authorization' => 'Bearer 你复制的API令牌' // 这里加令牌 ), ]); $response = $client->get('/products/page2'); echo $response->getReasonPhrase(); $body = $response->getBody(); echo $body; ?> - 最后要确保项目一的路由使用
api守卫,或者在路由里指定认证守卫:Route::get('/products/page2', [ProductController::class, 'page2'])->middleware('auth:sanctum');
注意事项
- 用Session Cookie的话,要注意Cookie的有效期,要是Cookie过期了就得重新复制
- 跨域名场景下,要确保项目一的
SESSION_DOMAIN配置允许项目二的域名访问,或者用子域名共享Cookie - API令牌要妥善保管,别泄露,要是泄露了可以在项目一的
personal_access_tokens表里删除对应的令牌
内容的提问来源于stack exchange,提问作者Alexandr
相关产品推荐
相关产品推荐

