Browse Source

feat: unified mfa service

M1Screw 2 years ago
parent
commit
fe5e7fec02

+ 1 - 1
README.md

@@ -37,7 +37,7 @@ SSPanel UIM 的需要以下程序才能正常的安装和运行:
 
 - Git
 - Nginx(必须使用 HTTPS/HTTPS is REQUIRED)
-- PHP 8.1+ (推荐开启 OPcache/OPcache is recommended)
+- PHP 8.1+ (推荐开启 OPcache & JIT /OPcache & JIT is highly recommended)
 - MariaDB 10.6+(关闭严格模式,不兼容 MySQL/Disable strict mode, DO NOT USE MYSQL)
 - Redis 7.0+
 

+ 5 - 16
src/Command/Tool.php

@@ -8,13 +8,13 @@ use App\Models\Link;
 use App\Models\Node;
 use App\Models\Setting;
 use App\Models\User as ModelsUser;
+use App\Services\MFA;
 use App\Utils\Hash;
 use App\Utils\Tools;
 use Exception;
 use Ramsey\Uuid\Uuid;
 use Telegram\Bot\Api;
 use Telegram\Bot\Exceptions\TelegramSDKException;
-use Vectorface\GoogleAuthenticator;
 use function count;
 use function date;
 use function fgets;
@@ -260,12 +260,8 @@ EOL;
         $users = ModelsUser::all();
 
         foreach ($users as $user) {
-            $secret = '';
-            $ga = new GoogleAuthenticator();
-
             try {
-                $secret = $ga->createSecret();
-                $user->ga_token = $secret;
+                $user->ga_token = MFA::generateGaToken();
                 $user->save();
             } catch (Exception $e) {
                 echo $e->getMessage();
@@ -291,6 +287,8 @@ EOL;
 
     /**
      * 创建 Admin 账户
+     *
+     * @throws Exception
      */
     public function createAdmin(): void
     {
@@ -342,16 +340,7 @@ EOL;
             $user->node_speedlimit = 0;
             $user->theme = $_ENV['theme'];
 
-            $ga = new GoogleAuthenticator();
-            $secret = '';
-
-            try {
-                $secret = $ga->createSecret();
-            } catch (Exception $e) {
-                echo $e->getMessage();
-            }
-
-            $user->ga_token = $secret;
+            $user->ga_token = MFA::generateGaToken();
             $user->ga_enable = 0;
 
             if ($user->save()) {

+ 3 - 8
src/Controllers/AuthController.php

@@ -11,6 +11,7 @@ use App\Services\Auth;
 use App\Services\Cache;
 use App\Services\Captcha;
 use App\Services\Mail;
+use App\Services\MFA;
 use App\Services\RateLimit;
 use App\Utils\Cookie;
 use App\Utils\Hash;
@@ -23,7 +24,6 @@ use Ramsey\Uuid\Uuid;
 use RedisException;
 use Slim\Http\Response;
 use Slim\Http\ServerRequest;
-use Vectorface\GoogleAuthenticator;
 use voku\helper\AntiXSS;
 use function array_rand;
 use function date;
@@ -106,10 +106,7 @@ final class AuthController extends BaseController
                 ]);
             }
 
-            $ga = new GoogleAuthenticator();
-            $rcode = $ga->verifyCode($user->ga_token, $code);
-
-            if (! $rcode) {
+            if (! MFA::verifyGa($user, $code)) {
                 // 记录登录失败
                 $user->collectLoginIP($_SERVER['REMOTE_ADDR'], 1);
 
@@ -286,9 +283,7 @@ final class AuthController extends BaseController
             $user->money = Setting::obtain('invitation_to_register_balance_reward');
         }
 
-        $ga = new GoogleAuthenticator();
-        $secret = $ga->createSecret();
-        $user->ga_token = $secret;
+        $user->ga_token = MFA::generateGaToken();
         $user->ga_enable = 0;
 
         $user->class_expire = date('Y-m-d H:i:s', time() + (int) $configs['sign_up_for_class_time'] * 86400);

+ 1 - 1
src/Controllers/User/InfoController.php

@@ -40,7 +40,7 @@ final class InfoController extends BaseController
         $themes = Tools::getDir(BASE_PATH . '/resources/views');
         $bind_token = Telegram::addBindSession($this->user);
         $methods = Config::getSupportParam('method');
-        $gaurl = MFA::getGAurl($this->user);
+        $gaurl = MFA::getGaUrl($this->user);
 
         return $response->write($this->view()
             ->assign('user', $this->user)

+ 16 - 21
src/Controllers/User/MFAController.php

@@ -5,11 +5,11 @@ declare(strict_types=1);
 namespace App\Controllers\User;
 
 use App\Controllers\BaseController;
+use App\Services\MFA;
 use Exception;
 use Psr\Http\Message\ResponseInterface;
 use Slim\Http\Response;
 use Slim\Http\ServerRequest;
-use Vectorface\GoogleAuthenticator;
 
 /**
  *  MFAController
@@ -27,11 +27,7 @@ final class MFAController extends BaseController
             ]);
         }
 
-        $user = $this->user;
-        $ga = new GoogleAuthenticator();
-        $rcode = $ga->verifyCode($user->ga_token, $code);
-
-        if (! $rcode) {
+        if (! MFA::verifyGa($this->user, $code)) {
             return $response->withJson([
                 'ret' => 0,
                 'msg' => '测试错误',
@@ -58,28 +54,27 @@ final class MFAController extends BaseController
         $user = $this->user;
         $user->ga_enable = $enable;
         $user->save();
+
+        if ($user->save()) {
+            return $response->withJson([
+                'ret' => 1,
+                'msg' => '设置成功',
+            ]);
+        }
+
         return $response->withJson([
-            'ret' => 1,
-            'msg' => '设置成功',
+            'ret' => 0,
+            'msg' => '设置失败',
         ]);
     }
 
+    /**
+     * @throws Exception
+     */
     public function resetGa(ServerRequest $request, Response $response, array $args): Response|ResponseInterface
     {
-        $ga = new GoogleAuthenticator();
-        $secret = '';
-
-        try {
-            $secret = $ga->createSecret();
-        } catch (Exception $e) {
-            return $response->withJson([
-                'ret' => 0,
-                'msg' => '重置失败',
-            ]);
-        }
-
         $user = $this->user;
-        $user->ga_token = $secret;
+        $user->ga_token = MFA::generateGaToken();
 
         if ($user->save()) {
             return $response->withJson([

+ 19 - 1
src/Services/MFA.php

@@ -4,9 +4,27 @@ declare(strict_types=1);
 
 namespace App\Services;
 
+use Exception;
+use Vectorface\GoogleAuthenticator;
+
 final class MFA
 {
-    public static function getGAurl($user): string
+    /**
+     * @throws Exception
+     */
+    public static function generateGaToken(): string
+    {
+        $ga = new GoogleAuthenticator();
+        return $ga->createSecret();
+    }
+
+    public static function verifyGa($user, string $code): bool
+    {
+        $ga = new GoogleAuthenticator();
+        return $ga->verifyCode($user->ga_token, $code);
+    }
+
+    public static function getGaUrl($user): string
     {
         return 'otpauth://totp/' .
             rawurlencode($_ENV['appName'] . ' (' . $user->email . ')') . '?secret=' . $user->ga_token;