directorytree / bartender
使用 Laravel Socialite 验证用户的一种有见地的方案。
Requires
- php: >=8.0
- illuminate/support: ^9.0|^10.0|^11.0
- laravel/socialite: ^5.0
Requires (Dev)
- orchestra/testbench: ^7.0|^8.0|^9.0
- pestphp/pest: ^1.0|^2.0
- phpunit/phpunit: ^9.0|^10.0
This package is auto-updated.
Last update: 2024-09-20 20:53:13 UTC
README
使用 Laravel Socialite 验证用户的一种有见地的方案。
Bartender 为您提供控制器、路由和默认实现,用于处理与 Laravel Socialite 提供程序的认证。
Bartender 中几乎所有的东西都可以自定义。
索引
要求
- PHP >= 8.0
- Laravel >= 9.0
- Laravel Socialite >= 5.0
安装
您可以通过 composer 安装此包
composer require directorytree/bartender
然后,发布迁移
它在
users
表上创建provider_id
和provider_name
列。
php artisan vendor:publish --provider="DirectoryTree\Bartender\BartenderServiceProvider"
最后,运行迁移
php artisan migrate
设置
使用 Bartender::routes()
注册认证路由。
这将注册 /auth/{driver}/redirect
和 /auth/{driver}/callback
路由。
// routes/web.php use DirectoryTree\Bartender\Facades\Bartender; Bartender::routes();
设置您需要的任何 Socialite 提供程序,并将每个提供程序的 redirect
URL 更新到您的 services.php
配置文件中
重要
请记住,为每个您希望使用的 Socialite 提供程序完全完成安装步骤。
如果您收到 驱动程序 [X] 不受支持
异常,您尚未完成提供程序的安装步骤。
// config/services.php return [ // ... 'google' => [ // ... 'redirect' => '/auth/google/callback', ], 'microsoft' => [ // ... 'redirect' => '/auth/microsoft/callback', ], ];
最后,使用 Bartender::serve()
在您的 AppServiceProvider
中注册 Socialite 提供程序
// app/Providers/AppServiceProvider.php use DirectoryTree\Bartender\Facades\Bartender; class AppServiceProvider extends ServiceProvider { // ... public function boot(): void { Bartender::serve('google'); Bartender::serve('microsoft'); } }
如果您的应用程序在 App\Models
命名空间之外使用 User
模型,您可以使用 Bartender
门面来设置它
如果您的应用程序在
App\Models
命名空间中使用默认的 LaravelUser
模型,请跳过此步骤。
// app/Providers/AuthServiceProvider.php use App\User; use DirectoryTree\Bartender\Facades\Bartender; class AuthServiceProvider extends ServiceProvider { // ... public function boot() { Bartender::setUserModel(User::class); } }
用法
将用户引导到 /auth/{driver}/redirect
路由以使用指定的驱动程序进行认证
<a href="{{ route('auth.driver.redirect', 'google') }}"> Login with Google </a> <a href="{{ route('auth.driver.redirect', 'microsoft') }}"> Login with Microsoft </a>
一旦用户成功认证,他们将被重定向到 /auth/{driver}/callback
路由,该路由将自动创建或更新他们的应用程序用户账户。
重要
如果您在点击登录链接时收到 路由要求 "driver" 不能为空
异常,您已忘记在 AppServiceProvider
中使用 Bartender::serve()
注册您的 Socialite 提供程序。
软删除
使用默认的 UserProviderRepository
,如果用户被软删除并且使用其提供程序登录,则用户将被恢复。
要更改此行为,请更换仓库。
电子邮件验证
使用默认的 UserProviderRepository
,如果用户的电子邮件尚未设置,则其电子邮件将自动验证(通过 email_verified_at
列)。
要更改此行为,请更换仓库。
扩展和自定义
Bartender 中几乎所有都可以更换。
如果您想自己处理 OAuth 重定向和回调,您可以创建自己的 ProviderHandler
// app/Socialite/UserProviderHandler.php namespace App\Socialite; use Illuminate\Http\Request; use Laravel\Socialite\Contracts\Provider; use DirectoryTree\Bartender\ProviderHandler; class UserProviderHandler implements ProviderHandler { /** * Constructor. */ public function __construct( protected Request $request ) { } /** * Handle redirecting the user to the OAuth provider. */ public function redirect(Provider $provider, string $driver): RedirectResponse { // Perform additional logic here... return $provider->redirect(); } /** * Handle an OAuth response from the provider. */ public function callback(Provider $provider, string $driver): RedirectResponse { // Authenticate the user your own way... return redirect()->route('dashboard'); } }
然后,将其提供给 Bartender::serve
方法的第二个参数
// app/Providers/AuthServiceProvider.php namespace App\Providers; use App\Socialite\UserProviderHandler; use DirectoryTree\Bartender\Facades\Bartender; class AuthServiceProvider extends ServiceProvider { // ... public function boot(): void { Bartender::serve('google', UserProviderHandler::class); Bartender::serve('microsoft', UserProviderHandler::class); } }
用户创建和更新
如果您想自定义默认处理程序中用户的创建,您可以创建自己的 ProviderRepository
实现
// app/Socialite/UserProviderRepository.php namespace App\Socialite; use App\Models\User; use Illuminate\Contracts\Auth\Authenticatable; use DirectoryTree\Bartender\ProviderRepository; use Laravel\Socialite\Contracts\User as SocialiteUser; class UserProviderRepository implements ProviderRepository { /** * Determine if the user already exists under a different provider. */ public function exists(string $driver, SocialiteUser $user): bool { return User::withTrashed()->where('...')->exists(); } /** * Update or create the socialite user. */ public function updateOrCreate(string $driver, SocialiteUser $user): Authenticatable { $user = User::withTrashed()->firstOrNew([ // ... ]); return $user; } }
然后,在您的 AppServiceProvider
中的服务容器中绑定您的实现
// app/Providers/AppServiceProvider.php namespace App\Providers; use App\Socialite\UserProviderRepository; use DirectoryTree\Bartender\ProviderRepository; class AppServiceProvider extends ServiceProvider { // ... public function register(): void { $this->app->bind(ProviderRepository::class, UserProviderRepository::class); } }
用户重定向和闪存消息
如果您想根据 OAuth 回调的结果自定义默认重定向器和闪存消息的行为,您可以创建自己的 ProviderRedirector
实现
建议在认证后重新生成会话,以防止用户利用会话固定攻击。
// app/Socialite/UserProviderRedirector.php namespace App\Socialite; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Session; class UserProviderRedirector implements ProviderRedirector { /** * Redirect when unable to authenticate the user. */ public function unableToAuthenticateUser(Exception $e, string $driver): RedirectResponse { report($e); return redirect()->route('login')->with('error', 'Unable to authenticate user.'); } /** * Redirect when the user already exists. */ public function userAlreadyExists(SocialiteUser $user, string $driver): RedirectResponse { return redirect()->route('login')->with('error', 'User already exists.'); } /** * Redirect when unable to create the user. */ public function unableToCreateUser(Exception $e, SocialiteUser $user, string $driver): RedirectResponse { report($e); return redirect()->route('login')->with('error', 'Unable to create user.'); } /** * Handle when the user has been successfully authenticated. */ public function userAuthenticated(Authenticatable $user, SocialiteUser $socialite, string $driver): RedirectResponse { Auth::login($user); Session::regenerate(); return redirect()->route('dashboard'); } }
然后,在您的 AppServiceProvider
中的服务容器中绑定您的实现
// app/Providers/AppServiceProvider.php namespace App\Providers; use App\Socialite\UserProviderRedirector; class AppServiceProvider extends ServiceProvider { // ... public function register(): void { $this->app->bind(ProviderRedirector::class, UserProviderRedirector::class); } }