Просмотр исходного кода

fix: 优化SSO回调页面code提取逻辑

优先从hash中提取code, 兼容 /#/auth/callback?code=xxx 格式
从search中提取code, 兼容 /auth/callback?code=xxx#/login 格式
kinglee 1 неделя назад
Родитель
Сommit
33860d89fa
1 измененных файлов с 28 добавлено и 17 удалено
  1. 28 17
      src/pages/auth/callback/index.tsx

+ 28 - 17
src/pages/auth/callback/index.tsx

@@ -4,10 +4,34 @@ import { history } from 'umi';
 import { request } from 'umi';
 import { DEFAULT_ENTER_PAGE } from '@/config/settings';
 
+/**
+ * 从 URL 中提取 code 参数
+ * 兼容两种 URL 格式:
+ * 1. /auth/callback?code=xxx#/login (SSO回调无hash)
+ * 2. /#/auth/callback?code=xxx (SSO回调带hash, 推荐)
+ */
+function extractCodeFromUrl(): { code: string | null; error: string | null; errorDesc: string | null } {
+  // 优先从 hash 中提取 (推荐格式: /#/auth/callback?code=xxx)
+  const hash = window.location.hash;
+  if (hash && hash.includes('?')) {
+    const hashQuery = hash.split('?')[1] || '';
+    const hashParams = new URLSearchParams(hashQuery);
+    const code = hashParams.get('code');
+    if (code) return { code, error: null, errorDesc: null };
+  }
+
+  // 从 search 中提取 (兼容格式: /auth/callback?code=xxx#/login)
+  const searchParams = new URLSearchParams(window.location.search);
+  return {
+    code: searchParams.get('code'),
+    error: searchParams.get('error'),
+    errorDesc: searchParams.get('error_description')
+  };
+}
+
 /**
  * SSO 回调页面
  * 从 URL 参数中提取 code,调用后端换码接口获取本地 JWT
- * URL: /auth/callback?code=xxxxxx
  */
 const SSOCallback = () => {
   const [loading, setLoading] = useState(true);
@@ -19,22 +43,11 @@ const SSOCallback = () => {
       if (processedRef.current) return;
       processedRef.current = true;
 
-      // 从完整 URL 中提取 code(兼容 hash 路由模式)
-      // URL 可能是 /auth/callback?code=xxx#/login 或 /auth/callback#/auth/callback?code=xxx
-      const href = window.location.href;
-      const hashIndex = href.indexOf('#');
-      const urlBeforeHash = hashIndex > -1 ? href.substring(0, hashIndex) : href;
-      const queryIndex = urlBeforeHash.indexOf('?');
-      const queryString = queryIndex > -1 ? urlBeforeHash.substring(queryIndex) : '';
-
-      const params = new URLSearchParams(queryString);
-      const code = params.get('code');
-      const error = params.get('error');
+      const { code, error, errorDesc } = extractCodeFromUrl();
 
       // 检查是否有 SSO 错误
       if (error) {
-        const errorDesc = params.get('error_description') || error;
-        message.error(`SSO 登录失败: ${errorDesc}`);
+        message.error(`SSO 登录失败: ${errorDesc || error}`);
         history.push(DEFAULT_ENTER_PAGE.login);
         return;
       }
@@ -53,7 +66,6 @@ const SSOCallback = () => {
         });
 
         if (result.code === '000000' && result.data) {
-          // 保存 Token 到 localStorage
           localStorage.setItem('token', result.data.token);
           if (result.data.refresh_token) {
             localStorage.setItem('refresh_token', result.data.refresh_token);
@@ -61,8 +73,7 @@ const SSOCallback = () => {
           localStorage.setItem('user', JSON.stringify(result.data.user));
 
           message.success('登录成功');
-
-          // 跳转首页 - 使用 replace 避免 back 回到 callback
+          // 使用 replace 避免后退回到回调页
           history.replace(DEFAULT_ENTER_PAGE.user);
         } else {
           message.error(result.message || '登录失败');