
Laravel Passport 在本地 Docker 环境中执行 artisan 命令时,因未生成密钥而提前触发密钥读取校验,导致 passport:keys 等命令无法执行;根本原因在于 AuthServiceProvider::boot() 中无条件初始化 AuthorizationServer,需在命令行环境下跳过该逻辑。
laravel passport 在本地 docker 环境中执行 artisan 命令时,因未生成密钥而提前触发密钥读取校验,导致 `passport:keys` 等命令无法执行;根本原因在于 `authserviceprovider::boot()` 中无条件初始化 authorizationserver,需在命令行环境下跳过该逻辑。
在 Laravel 8+ 项目中,当使用 Laravel Passport 进行 API 认证时,若 storage/oauth-private.key 和 storage/oauth-public.key 尚未生成(例如全新部署或本地 Docker 初始化阶段),执行 php artisan passport:keys 却仍报错 Unable to read key from file file:///var/www/html/storage/oauth-private.key,这看似矛盾——因为密钥本就应由该命令生成,却在命令执行前就被强制校验。
问题根源在于:AuthServiceProvider 的 boot() 方法中,直接调用了 $this->app->make(AuthorizationServer::class) 并配置了授权类型(如 PersonalAccessGrant)。而 AuthorizationServer 构造过程中会立即尝试加载私钥文件,无论当前是否处于 HTTP 请求上下文还是 Artisan 命令行上下文。这意味着:哪怕你只是运行 php artisan list,只要 AuthServiceProvider 已注册并启用,就会触发密钥读取逻辑,从而导致命令失败。
✅ 正确解法是在 AuthServiceProvider.php 的 boot() 方法开头添加运行环境判断,仅在 HTTP 请求期间初始化授权服务器,避免命令行场景下提前加载密钥:
// app/Providers/AuthServiceProvider.php
public function boot()
{
// ✅ 关键修复:跳过命令行环境下的 AuthorizationServer 初始化
if ($this->app->runningInConsole()) {
return;
}
$server = $this->app->make(AuthorizationServer::class);
$server->enableGrantType(
new PersonalAccessGrant(),
new DateInterval('P' . config('passport.token_lifetime', 365) . 'D')
);
}⚠️ 注意事项:
- 此修复适用于 Laravel 8.0 及后续版本(包括 Laravel 9/10),且与 Passport 10.x 兼容;
- 确保
config/auth.php中apiguard 的driver设置为passport,否则即使密钥生成成功也无法生效; - 执行修复后,首次运行
php artisan passport:install或php artisan passport:keys即可成功生成密钥对(默认存于storage/目录); - 若使用 Docker,请确认
storage/目录具有写入权限(如chown -R www-data:www-data storage/),并挂载卷时保留该目录结构; - 生产环境部署时,建议将密钥文件通过
.env或 secrets 注入,而非依赖passport:keys动态生成,以增强安全性与一致性。
完成上述调整后,所有 Artisan 命令均可正常执行,Passport 密钥生成流程回归预期行为——真正实现“先生成、再使用”。


















