From 66d9f22f6e9a1a860b60723dbd2205ec218c8fac Mon Sep 17 00:00:00 2001 From: BrettonYe Date: Mon, 8 Apr 2024 23:31:36 +0800 Subject: [PATCH] Fixed OAuth not function and improve the code quality --- app/Http/Controllers/OAuthController.php | 180 +++++++++++++---------- resources/views/auth/login.blade.php | 8 +- resources/views/auth/register.blade.php | 8 +- resources/views/user/profile.blade.php | 16 +- routes/web.php | 10 +- 5 files changed, 122 insertions(+), 100 deletions(-) diff --git a/app/Http/Controllers/OAuthController.php b/app/Http/Controllers/OAuthController.php index 21404f41..77127c45 100644 --- a/app/Http/Controllers/OAuthController.php +++ b/app/Http/Controllers/OAuthController.php @@ -13,118 +13,140 @@ use Str; class OAuthController extends Controller { - public function simple(string $type): RedirectResponse - { - $info = Socialite::driver($type)->stateless()->user(); - if ($info) { - $user = Auth::user(); - - if ($user) { - return $this->binding($type, $user, $info); - } - - return $this->logging($type, $info); - } - - return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed')); - } - - private function binding(string $type, User $user, \Laravel\Socialite\Contracts\User $OauthUser): RedirectResponse - { - $data = ['type' => $type, 'identifier' => $OauthUser->getId(), 'credential' => $OauthUser->token]; - if ($user->userAuths()->whereType($type)->updateOrCreate($data)) { - return redirect()->route('profile')->with('successMsg', trans('auth.oauth.bind_success')); - } - - return redirect()->route('profile')->withErrors(trans('auth.oauth.bind_failed')); - } - - private function logging(string $type, \Laravel\Socialite\Contracts\User $OauthUser): RedirectResponse - { - $user = User::whereUsername($OauthUser->getEmail())->first(); - if (! isset($user)) { - $auth = UserOauth::whereType($type)->whereIdentifier($OauthUser->getId())->first(); - if (isset($auth)) { - $user = $auth->user; - } - } - - if (isset($user)) { - Auth::login($user); - Helpers::userLoginAction($user, IP::getClientIp()); // 用户登录后操作 - - return redirect()->route('login'); - } - - return redirect()->route('login')->withErrors(trans('auth.error.not_found_user')); - } - - public function login(string $type): RedirectResponse - { - $info = Socialite::driver($type)->stateless()->user(); - if ($info) { - return $this->logging($type, $info); - } - - return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed')); - } - - public function unbind(string $type): RedirectResponse + public function unbind(string $provider): RedirectResponse { $user = Auth::user(); - if ($user && $user->userAuths()->whereType($type)->delete()) { + + if ($user && $user->userAuths()->whereType($provider)->delete()) { return redirect()->route('profile')->with('successMsg', trans('auth.oauth.unbind_success')); } - return redirect()->route('profile')->with('successMsg', trans('auth.oauth.unbind_failed')); + return redirect()->route('profile')->withErrors(trans('auth.oauth.unbind_failed')); } - public function bind(string $type): RedirectResponse + public function bind(string $provider): RedirectResponse { - $info = Socialite::driver($type)->stateless()->user(); + config(["services.$provider.redirect" => route('oauth.bind', ['provider' => $provider])]); + $authInfo = Socialite::driver($provider)->stateless()->user(); - if ($info) { - $user = Auth::user(); - if ($user) { - return $this->binding($type, $user, $info); - } + if (! $authInfo) { + return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed')); + } + $user = Auth::user(); + + if (! $user) { return redirect()->route('profile')->withErrors(trans('auth.oauth.bind_failed')); } - return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed')); + return $this->bindLogic($provider, $user, $authInfo); } - public function register(string $type): RedirectResponse + private function bindLogic(string $provider, User $user, \Laravel\Socialite\Contracts\User $authInfo): RedirectResponse { + $data = [ + 'type' => $provider, + 'identifier' => $authInfo->getId(), + 'credential' => $authInfo->token, + ]; + + $auth = $user->userAuths()->whereType($provider)->first(); + + if ($auth) { + $user->userAuths()->whereType($provider)->update($data); + $message = trans('auth.oauth.rebind_success'); + } else { + $user->userAuths()->create($data); + $message = trans('auth.oauth.bind_success'); + } + + return redirect()->route('profile')->with('successMsg', $message); + } + + public function register(string $provider): RedirectResponse + { + config(["services.$provider.redirect" => route('oauth.register', ['provider' => $provider])]); if (! sysConfig('is_register')) { return redirect()->route('register')->withErrors(trans('auth.register.error.disable')); } - if ((int) sysConfig('is_invite_register') === 2) { // 必须使用邀请码 + if ((int) sysConfig('is_invite_register') === 2) { return redirect()->route('register')->withErrors(trans('validation.required', ['attribute' => trans('auth.invite.attribute')])); } - $OauthUser = Socialite::driver($type)->stateless()->user(); + $registerInfo = Socialite::driver($provider)->stateless()->user(); - if ($OauthUser) { - if (User::whereUsername($OauthUser->getEmail())->doesntExist() && UserOauth::whereIdentifier($OauthUser->getId())->doesntExist()) { // 排除重复用户注册 - $user = Helpers::addUser($OauthUser->getEmail(), Str::random(), MiB * sysConfig('default_traffic'), (int) sysConfig('default_days'), $OauthUser->getNickname()); + if (! $registerInfo) { + return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed')); + } + + $user = User::whereUsername($registerInfo->getEmail())->first(); + + if (! $user) { // 邮箱未被注册 + $userAuth = UserOauth::whereType($provider)->whereIdentifier($registerInfo->getId())->first(); + + if (! $userAuth) { // 第三方账号未被绑定 + $user = Helpers::addUser($registerInfo->getEmail(), Str::random(), MiB * sysConfig('default_traffic'), (int) sysConfig('default_days'), $registerInfo->getNickname()); $user->userAuths()->create([ - 'type' => $type, - 'identifier' => $OauthUser->getId(), - 'credential' => $OauthUser->token, + 'type' => $provider, + 'identifier' => $registerInfo->getId(), + 'credential' => $registerInfo->token, ]); - Auth::login($user); + return $this->handleLogin($user); + } + } - return redirect()->route('login'); + return redirect()->route('login')->withErrors(trans('auth.oauth.registered')); + } + + private function handleLogin(User $user): RedirectResponse + { + Auth::login($user); + Helpers::userLoginAction($user, IP::getClientIp()); + + return redirect()->route('login'); + } + + public function login(string $provider): RedirectResponse + { + config(["services.$provider.redirect" => route('oauth.login', ['provider' => $provider])]); + $authInfo = Socialite::driver($provider)->stateless()->user(); + + if ($authInfo) { + $auth = UserOauth::whereType($provider)->whereIdentifier($authInfo->getId())->first(); + + if ($auth && ($user = $auth->user)) { // 如果第三方登录有记录,直接登录用户 + return $this->handleLogin($user); } - return redirect()->route('login')->withErrors(trans('auth.oauth.registered')); + $user = User::whereUsername($authInfo->getEmail())->first(); + + if ($user) { // 如果用户存在,执行绑定逻辑并登录用户 + $this->bindLogic($provider, $user, $authInfo); + + return $this->handleLogin($user); + } + + // 如果用户不存在,则返回错误消息 + return redirect()->route('login')->withErrors(trans('auth.error.not_found_user')); } return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed')); } + + public function redirect(string $provider, string $operation = 'login'): RedirectResponse + { + $redirectRoutes = [ + 'bind' => 'oauth.bind', + 'register' => 'oauth.register', + 'login' => 'oauth.login', + ]; + + $key = "services.$provider.redirect"; + config([$key => route($redirectRoutes[$operation], ['provider' => $provider])]); + + return Socialite::driver($provider)->stateless()->redirect(); + } } diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 43510f04..ee9b031b 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -36,14 +36,14 @@
{{ trans('auth.one-click_login') }}
- @foreach (json_decode(sysConfig('oauth_path')) as $item) - @if ($item === 'telegram') + @foreach (json_decode(sysConfig('oauth_path')) as $provider) + @if ($provider === 'telegram')
{!! Socialite::driver('telegram')->getButton() !!}
@else - - + + @endif @endforeach diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index fde4f0e4..e354b070 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -106,10 +106,10 @@
{{trans('auth.oauth.register')}}
- @foreach (json_decode(sysConfig('oauth_path')) as $item) - @if ($item !== 'telegram') - - + @foreach (json_decode(sysConfig('oauth_path')) as $provider) + @if ($provider !== 'telegram') + + @endif @endforeach diff --git a/resources/views/user/profile.blade.php b/resources/views/user/profile.blade.php index 9c4f63a9..985e48de 100644 --- a/resources/views/user/profile.blade.php +++ b/resources/views/user/profile.blade.php @@ -42,22 +42,22 @@ {{trans('user.oauth.bind_title')}}
- @foreach (json_decode(sysConfig('oauth_path')) as $item) - - {{ ucfirst($item) }} + @foreach (json_decode(sysConfig('oauth_path')) as $provider) + + {{ ucfirst($provider) }} : - @if(in_array($item, $auth, true)) + @if(in_array($provider, $auth, true)) {{trans('user.oauth.rebind')}} @else {{trans('user.oauth.not_bind')}} @endif - @if($item === 'telegram') + @if($provider === 'telegram') {!! Socialite::driver('telegram')->getButton() !!} @endif - @if(in_array($item, $auth, true)) - {{trans('user.oauth.unbind')}} + @if(in_array($provider, $auth, true)) + {{trans('user.oauth.unbind')}} @endif @endforeach
diff --git a/routes/web.php b/routes/web.php index 40383eaf..ee0a60d5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -22,11 +22,11 @@ Route::get('/message/{type}/{msg_id}/show', [MessageController::class, 'index']) Route::middleware(['isForbidden', 'affiliate', 'isMaintenance'])->group(function () { // 登录相关 Route::prefix('oauth')->name('oauth.')->controller(OAuthController::class)->group(function () { // 用户第三方登录默认登录/转跳方式 - Route::get('{type}/login', 'login')->name('login'); - Route::get('{type}/register', 'register')->name('register'); - Route::get('{type}/bind', 'bind')->name('bind'); - Route::get('{type}/unbind', 'unbind')->name('unbind'); - Route::get('{type}/redirect', 'simple')->name('simple'); + Route::get('{provider}/redirect/{operation}', 'redirect')->whereIn('operation', ['bind', 'register', 'login'])->name('route'); // 转跳 + Route::get('{provider}/unbind', 'unbind')->name('unbind'); // 解绑 + Route::get('{provider}/login', 'login')->name('login'); // 登录 callback + Route::get('{provider}/register', 'register')->name('register'); // 注册 callback + Route::get('{provider}/bind', 'bind')->name('bind'); // 绑定 callback }); Route::controller(AuthController::class)->group(function () {