Explorar el Código

Merge branch 'login_0407_liu'

rkljw hace 3 semanas
padre
commit
ecc18dc8b7
Se han modificado 2 ficheros con 175 adiciones y 1 borrados
  1. 172 0
      app/Controller/LoginController.php
  2. 3 1
      config/api/login.php

+ 172 - 0
app/Controller/LoginController.php

@@ -14,6 +14,7 @@ use Hyperf\HttpServer\Annotation\AutoController;
 use Hyperf\Validation\Contract\ValidatorFactoryInterface;
 use \Phper666\JWTAuth\JWT;
 use App\Model\UserToken;
+use Hyperf\HttpServer\Response;
 /**
  * @AutoController()
  */
@@ -28,6 +29,14 @@ class LoginController extends AbstractController
      */
     #[Inject]
     private $userServiceClient;
+    /**
+     * @var Response
+     */
+//    private $response;
+//    public function __construct(Response $response)
+//    {
+//        $this->response = $response;
+//    }
     public function login(Jwt $jwt)
     {
 
@@ -434,6 +443,169 @@ class LoginController extends AbstractController
 
     public function goLogin()
     {
+        // 获取请求数据并设置默认值
+        $reqData = $this->request->all();
+        // 安全过滤 Admin-Token 和 ticket
+        $adminToken = !empty($_COOKIE['Admin-Token']) ? $this->sanitizeInput($_COOKIE['Admin-Token']) : '';
+        $ticket = !empty($reqData['ticket']) ? $this->sanitizeInput($reqData['ticket']) : '';
+        $backurl = $this->sanitizeBackUrl($reqData['backurl'] ?? $_SERVER['HTTP_REFERER'] ?? '');
+
+        // 校验 THE_HOST 环境变量
+        $theHost = env("THE_HOST");
+        if (empty($theHost)) {
+            return Result::error('系统配置错误:THE_HOST 未定义');
+        }
+
+        // 如果存在 adminToken,则进行登录校验
+        if (!empty($adminToken)) {
+            try {
+                $redis = $this->container->get(\Hyperf\Redis\Redis::class);
+
+                // 如果 ticket 存在且有效,则直接跳转
+                if (!empty($ticket) && $redis->exists('ticket:' . $ticket)) {
+                    $this->redirectWithTicket($backurl, $ticket, $adminToken);
+    //                return;
+                }
+
+                // 如果 ticket 不存在或无效,则重新生成 ticket 并跳转
+                if (empty($ticket)) {
+                    $ticket = md5($adminToken);
+                }
+
+                // 跳转到目标页面
+                $this->redirectWithTicket($backurl, $ticket, $adminToken);
+    //            return;
+            } catch (\Throwable $e) {
+                // 记录异常日志
+//                \Hyperf\Logger\LoggerFactory::get('default')->error('Redis 操作失败: ' . $e->getMessage());
+                // 捕获 Redis 异常,返回错误信息
+                return Result::error('系统错误:Redis 操作失败');
+            }
+        }
+        // 如果没有 adminToken,则跳转到登录页面
+        $loginUrl = 'http://' . $theHost . '/#/login?backurl=' . urlencode($backurl);
+        return $this->response->redirect($loginUrl, 302);
+    }
+
+    /**
+     * 安全过滤输入数据
+     * @param string $input
+     * @return string
+     */
+    private function sanitizeInput(string $input): string
+    {
+        return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
+    }
+
+    /**
+     * 校验并清理 backurl
+     * @param string $backurl
+     * @return string
+     */
+    private function sanitizeBackUrl(string $backurl): string
+    {
+        // 解码并去除多余字符
+        $decodedUrl = urldecode($backurl);
+        return filter_var($decodedUrl, FILTER_VALIDATE_URL) ?: '';
+    }
 
+    /**
+     * 跳转到目标页面
+     * @param string $backurl
+     * @param string $ticket
+     * @param string $adminToken
+     */
+    private function redirectWithTicket(string $backurl, string $ticket, string $adminToken)
+    {
+        $backurl = rtrim($backurl, '/');
+        $redirectUrl = $this->fun_http($backurl . '?ticket=' . $ticket . '&admintoken=' . urlencode($adminToken));
+        return $this->response->redirect($redirectUrl, 302);
+    }
+
+    /**
+     * 处理 URL
+     * @param string $url
+     * @return string
+     */
+    private function fun_http(string $url): string
+    {
+        // 确保 URL 以 http 或 https 开头
+        if (!preg_match('/^https?:\/\//i', $url)) {
+            $url = 'http://' . $url;
+        }
+        return $url;
     }
+
+    /**
+     * 退出
+     * @return void
+     */
+    public function logout(Jwt $jwt)
+    {
+        $reqData = $this->request->all();
+        $validator = $this->validationFactory->make(
+            $reqData,
+            [
+                'backurl' => 'required',
+                'admintoken' => 'required',
+            ],
+            [
+                'backurl.required' => 'backurl不能为空',
+                'admintoken.required' => 'admintoken不能为空',
+            ]
+        );
+        if ($validator->fails()) {
+            $errorMessage = $validator->errors()->first();
+            return Result::error($errorMessage);
+        }
+
+        $redis = $this->container->get(\Hyperf\Redis\Redis::class);
+        $ticket = md5($reqData['admintoken']);
+        $isDel = 0;
+        if ($redis->exists('ticket:' . $ticket)) {
+            $res = $redis->del('ticket:' . $ticket);
+            if (!!$res && $res == 1) $isDel = 1;
+        }else{
+            $isDel = 1;
+        }
+        setcookie("Admin-Token", "", time(), "/");
+        $jwt->logout($reqData['admintoken']);
+        $backurl = $this->fun_http($reqData['backurl']);
+
+        return $this->response->redirect($backurl, 302);
+    }
+
+    /**
+     * 登录回调
+     * @return void
+     */
+    public function backlogin()
+    {
+        $reqData = $this->request->all();
+        $validator = $this->validationFactory->make(
+            $reqData,
+            [
+                'backurl' => 'required',
+                'token' => 'required',
+            ],
+            [
+                'backurl.required' => 'backurl不能为空',
+                'token.required' => 'token不能为空',
+            ]
+        );
+        if ($validator->fails()) {
+            $errorMessage = $validator->errors()->first();
+            return Result::error($errorMessage);
+        }
+        $redis = $this->container->get(\Hyperf\Redis\Redis::class);
+        $ticket = md5($reqData['token']);
+        $res = $redis->set('ticket:' . $ticket, $reqData['token'],  3600*24);
+        if($res && !empty($ticket)){
+            $url = $reqData['backurl'] . '/?ticket=' . $ticket . '&admintoken=' . urlencode($reqData['token']);
+            $url = $this->fun_http($url);
+            return $this->response->redirect($url, 302);
+        }
+    }
+
+
 }

+ 3 - 1
config/api/login.php

@@ -20,8 +20,10 @@ Router::get('/api/loginStatus', 'App\Controller\LoginController@loginStatus');
 Router::get('/api/loginapi', 'App\Controller\LoginController@loginapi');
 //退出登陆
 Router::get('/api/logoutapi', 'App\Controller\LoginController@logoutapi');
-
+//跳转登陆
 Router::get('/api/goLogin', 'App\Controller\LoginController@goLogin');
+//退出登陆
 Router::get('/api/logout', 'App\Controller\LoginController@logout');
+//返回登陆
 Router::get('/api/backlogin', 'App\Controller\LoginController@backlogin');