laravel用socialite集成github或qq登录核心为三步:装包、配配置、写回调;但qq非官方驱动,需额外适配包(如overtrue/laravel-socialite-qq),否则报invalidstateexception或无法获取用户信息。

直接说结论:Laravel 用 Socialite 接 github 或 QQ 登录,核心就三步——装包、配配置、写回调逻辑;但 QQ 登录不是官方驱动,得手动补适配,否则会卡在「InvalidStateException」或拿不到用户信息。
装 Socialite 并确认驱动支持
Socialite 默认只带 GitHub、gitlab、Twitter 等标准 OAuth2 驱动,QQ 是国内特例:它用的是 OAuth 1.0a 协议(老版),且返回字段、签名方式、Token 获取流程都和标准 OAuth2 不兼容。所以:
- GitHub 登录:直接
composer require laravel/socialite,开箱即用 - QQ 登录:必须额外装适配包,比如
overtrue/laravel-socialite-qq(注意选 Laravel 版本匹配的分支) - Laravel 10+ 用户需确认
socialite版本 ≥ 5.6,否则不支持 PHP 8.2+ 的某些类型声明
配置 .env 和 config/services.php
GitHub 和 QQ 的配置项命名不同,且 QQ 要求额外填 qq_redirect(不是 redirect):
## .env GITHUB_CLIENT_ID=xxx GITHUB_CLIENT_SECRET=xxx GITHUB_REDIRECT_URI=https://yoursite.com/login/github/callback <p>QQ_APP_ID=xxx QQ_APP_KEY=xxx QQ_REDIRECT_URI=<a href="https://www.php.cn/link/632fb5fbe4d5514c423d7622626e7ee7">https://www.php.cn/link/632fb5fbe4d5514c423d7622626e7ee7</a>
然后在 config/services.php 里对齐:
'github' => [ 'client_id' => env('GITHUB_CLIENT_ID'), 'client_secret' => env('GITHUB_CLIENT_SECRET'), 'redirect' => env('GITHUB_REDIRECT_URI'), ], <p>'qq' => [ 'client_id' => env('QQ_APP_ID'), 'client_secret' => env('QQ_APP_KEY'), 'redirect' => env('QQ_REDIRECT_URI'), // 注意:有些 QQ 适配包实际读的是 'qq_redirect' ],
⚠️ 容易踩坑:QQ 开发平台后台填写的「授权回调域」必须和 QQ_REDIRECT_URI 的域名完全一致(不能带 path,也不能是 localhost —— 测试得用 ngrok 或内网穿透)。
路由 + 控制器实现登录跳转与回调
GitHub 可直接用 Socialite::driver('github')->redirect();QQ 必须确保用了正确的 driver 实例(比如 Socialite::driver('qq'),而不是误写成 'qq_oauth'):
// routes/web.php Route::get('/login/github', [LoginController::class, 'redirectToGithub']); Route::get('/login/github/callback', [LoginController::class, 'handleGithubCallback']); <p>Route::get('/login/qq', [LoginController::class, 'redirectToQq']); Route::get('/login/qq/callback', [LoginController::class, 'handleQqCallback']);
控制器里关键点:
- 跳转前别漏掉
session()->put('state', $socialite->getState())(QQ 适配包通常自动处理,但自定义驱动时容易丢) - 回调里必须用
user()拿数据,不是stateless()(QQ 不支持无状态模式) - GitHub 返回的
$user->getId()是数字 ID;QQ 返回的$user->getId()是字符串(如"123456789"),存数据库时字段别设成unsignedBigInteger
用户绑定与 token 处理的常见断点
拿到第三方用户后,不能直接 Auth::login($user) —— 因为 $user 是 SocialiteUser 实例,不是 Eloquent 模型。典型做法是:
- 查
User::where('provider_id', $socialiteUser->getId())->where('provider', 'github')->first() - 没找到就新建:用
$socialiteUser->getEmail()和$socialiteUser->getName()初始化,但注意 QQ 的getEmail()永远返回 NULL(它不开放邮箱),得用$socialiteUser->getNickname()+ 时间戳生成唯一邮箱占位 - 保存后调用
Auth::login($existingOrNewUser),别忘了return redirect()->intended('/')
最常被忽略的一点:QQ 登录成功后,$user->token 是临时 access_token,不能长期保存;GitHub 的 token 默认有效期长,但也不建议直接存进数据库明文字段——该用 Laravel Passport 或 Sanctum 做二次 token 化。