diff --git a/.env.example b/.env.example index 5e47bfe..36999f9 100644 --- a/.env.example +++ b/.env.example @@ -107,3 +107,9 @@ ROADRUNNER_VERSION= # 实人认证的配置 SUPPORT_REAL_NAME_APP_CODE= +# OAuth +OAUTH_CLIENT_ID= +OAUTH_CLIENT_SECRET= +OAUTH_REDIRECT=${APP_URL}/auth/callback +OAUTH_DOMAIN=http://oauth.test + diff --git a/app/Http/Controllers/Web/AuthController.php b/app/Http/Controllers/Web/AuthController.php index 4cb22e8..c51319d 100644 --- a/app/Http/Controllers/Web/AuthController.php +++ b/app/Http/Controllers/Web/AuthController.php @@ -5,15 +5,19 @@ use App\Http\Controllers\Controller; use App\Models\User; use App\Notifications\User\UserNotification; -use function back; -use function config; +use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Http; +use Illuminate\Support\Str; use Illuminate\View\View; +use function back; +use function config; use function redirect; use function session; use function view; @@ -33,13 +37,13 @@ public function index(Request $request): View|RedirectResponse $dashboardHost = parse_url(config('settings.dashboard.base_url'), PHP_URL_HOST); if ($callbackHost === $dashboardHost) { - if (! $request->user('web')->isRealNamed()) { + if (!$request->user('web')->isRealNamed()) { return redirect()->route('real_name.create')->with('status', '重定向已被打断,需要先实人认证。'); } $token = $request->user()->createToken('Dashboard')->plainTextToken; - return redirect($callback.'?token='.$token); + return redirect($callback . '?token=' . $token); } session(['referer.domain' => parse_url($request->header('referer'), PHP_URL_HOST)]); @@ -124,7 +128,7 @@ public function exitSudo(): RedirectResponse public function showAuthRequest($token): View|RedirectResponse { - $data = Cache::get('auth_request:'.$token); + $data = Cache::get('auth_request:' . $token); if (empty($data)) { return redirect()->route('index')->with('error', '登录请求的 Token 不存在或已过期。'); @@ -148,7 +152,7 @@ public function storeAuthRequest(Request $request): RedirectResponse|View 'token' => 'required|string|max:128', ]); - $data = Cache::get('auth_request:'.$request->input('token')); + $data = Cache::get('auth_request:' . $request->input('token')); if (empty($data)) { return back()->with('error', '登录请求的 Token 不存在或已过期。'); @@ -172,10 +176,10 @@ public function storeAuthRequest(Request $request): RedirectResponse|View $data['token'] = $user->createToken($data['meta']['description'] ?? Carbon::now()->toDateString(), $abilities)->plainTextToken; } - Cache::put('auth_request:'.$request->input('token'), $data, 60); + Cache::put('auth_request:' . $request->input('token'), $data, 60); if (isset($data['meta']['return_url']) && $data['meta']['return_url']) { - return redirect()->to($data['meta']['return_url'].'?auth_request='.$request->input('token')); + return redirect()->to($data['meta']['return_url'] . '?auth_request=' . $request->input('token')); } return redirect()->route('index')->with('success', '登录请求已确认。'); @@ -183,8 +187,8 @@ public function storeAuthRequest(Request $request): RedirectResponse|View public function fastLogin(string $token): RedirectResponse { - $cache_key = 'session_login:'.$token; - $user_id = Cache::get('session_login:'.$token); + $cache_key = 'session_login:' . $token; + $user_id = Cache::get('session_login:' . $token); if (empty($user_id)) { return redirect()->route('index')->with('error', '登录请求的 Token 不存在或已过期。'); @@ -202,4 +206,81 @@ public function fastLogin(string $token): RedirectResponse return redirect()->route('index'); } + + public function redirect(Request $request) + { + $request->session()->put('state', $state = Str::random(40)); + + $query = http_build_query([ + 'client_id' => config('oauth.client_id'), + 'redirect_uri' => config('oauth.callback_uri'), + 'response_type' => 'code', + 'scope' => config('oauth.scope'), + 'state' => $state, + ]); + + return redirect()->to(config('oauth.oauth_auth_url') . '?' . $query); + } + + public function callback(Request $request) + { + try { + $authorize = Http::asForm()->throw()->post(config('oauth.oauth_token_url'), [ + 'grant_type' => 'authorization_code', + 'client_id' => config('oauth.client_id'), + 'client_secret' => config('oauth.client_secret'), + 'redirect_uri' => config('oauth.callback_uri'), + 'code' => $request->input('code'), + ])->getBody(); + } catch (Exception $e) { + return redirect()->route('index')->with('error', '无法获取授权。' . $e->getMessage()); + } + + $authorize = json_decode($authorize); + + $http = Http::asForm()->withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $authorize->access_token + ])->throw(); + + $oauth_user = $http->get(config('oauth.oauth_user_url'))->object(); + $real_name = $http->get(config('oauth.oauth_real_name_url'))->object(); + + $user_sql = User::where('email', $oauth_user->email); + $user = $user_sql->first(); + + if (is_null($user)) { + $name = $oauth_user->name; + $email = $oauth_user->email; + $email_verified_at = $oauth_user->email_verified_at; + + $user = new User(); + + $user->name = $name; + $user->email = $email; + $user->email_verified_at = $email_verified_at; + $user->real_name_verified_at = $real_name->real_name_verified_at; + $user->real_name = $real_name->real_name; + $user->id_card = $real_name->id_card; + + + $user->password = Hash::make(Str::random(16)); + + + $user->save(); + + $request->session()->put('auth.password_confirmed_at', time()); + } else { + if ($user->name != $oauth_user->name) { + User::where('email', $oauth_user->email)->update([ + 'name' => $oauth_user->name + ]); + } + } + + Auth::guard('web')->loginUsingId($user->id, true); + + return redirect()->route('index'); + } + } diff --git a/app/Models/User.php b/app/Models/User.php index 9d9eeaf..23d84c5 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -158,7 +158,7 @@ public function selectPublic(): self|Builder|CachedBuilder // 仅需选择公开的 return $this->select($this->publics); } - + public function getOnlyPublic($appened_excepts = [], $display = []): array { if ($display) { diff --git a/config/oauth.php b/config/oauth.php new file mode 100644 index 0000000..2fef1f3 --- /dev/null +++ b/config/oauth.php @@ -0,0 +1,12 @@ + env('OAUTH_REDIRECT'), + 'client_id' => env('OAUTH_CLIENT_ID'), + 'client_secret' => env('OAUTH_CLIENT_SECRET'), + 'oauth_auth_url' => env('OAUTH_DOMAIN') . '/oauth/authorize', + 'oauth_token_url' => env('OAUTH_DOMAIN') . '/oauth/token', + 'oauth_user_url' => env('OAUTH_DOMAIN') . '/api/user', + 'oauth_real_name_url' => env('OAUTH_DOMAIN') . '/api/real-name', + 'scope' => 'realname login user', +]; diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 20f7b7d..a0b1bc2 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -8,169 +8,15 @@ -

注册 或 登录

+

使用 LoliArt Account 登录。

-
- @csrf + 使用 LoliArt Account 登录 -
- -
- -
-
- -
- - - {{ __('Forgot Your Password?') }} - -
- -
-
- - @error('password') - - {{ $message }} - - @enderror -
-
- - -
- - -
- -
- -
- - - -
如果您继续,则代表您已经阅读并同意 服务条款 -
- - -
- - - @endsection diff --git a/routes/web.php b/routes/web.php index f4debce..b644fe3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,8 +19,8 @@ Route::get('/', [AuthController::class, 'index'])->middleware('banned')->name('index'); Route::prefix('auth')->group(function () { - Route::get('login', [LoginController::class, 'showLoginForm'])->name('login'); - Route::post('login', [LoginController::class, 'login']); + // Route::get('login', [LoginController::class, 'showLoginForm'])->name('login'); + // Route::post('login', [LoginController::class, 'login']); Route::post('logout', [LoginController::class, 'logout'])->name('logout'); Route::post('exists', [LoginController::class, 'userIfExists'])->name('login.exists-if-user'); @@ -40,6 +40,9 @@ Route::post('email/resend', [VerificationController::class, 'resend'])->name('verification.resend'); Route::get('token/{token}', [AuthController::class, 'fastLogin'])->name('auth.fast-login'); + + Route::get('redirect', [AuthController::class, 'redirect'])->name('login'); + Route::get('callback', [AuthController::class, 'callback'])->name('callback'); }); Route::middleware(['auth:web', 'banned', 'verified'])->group(