فهرست منبع

fix: 修复SSO回调在hash路由模式下的code提取问题

1. app.tsx: 在getInitialState中检测SSO回调URL缺少hash的情况,
   自动将 /auth/callback?code=xxx 转为 /auth/callback#/auth/callback?code=xxx
2. callback/index.tsx: 从完整URL中提取code,兼容hash路由模式
   添加防重复执行保护,成功后使用replace避免返回
kinglee 1 هفته پیش
والد
کامیت
719cdf0321
2فایلهای تغییر یافته به همراه24 افزوده شده و 4 حذف شده
  1. 7 0
      src/app.tsx
  2. 17 4
      src/pages/auth/callback/index.tsx

+ 7 - 0
src/app.tsx

@@ -124,6 +124,13 @@ export async function getInitialState(): Promise<{
   // SSO 回调页面不需要获取用户信息,等待换码完成
   // SSO 回调页面不需要获取用户信息,等待换码完成
   const isSSOCallback = location.pathname.startsWith('/auth/callback');
   const isSSOCallback = location.pathname.startsWith('/auth/callback');
 
 
+  // hash 路由模式下,SSO 平台回调 URL 不带 hash,
+  // 需要把 /auth/callback?code=xxx 转为 /auth/callback#/auth/callback?code=xxx
+  if (isSSOCallback && !location.pathname.includes('#') && !location.hash.startsWith('#/auth/callback')) {
+    const search = location.search;
+    history.replace(`/auth/callback#${location.pathname}${search}`);
+  }
+
   if (![DEFAULT_ENTER_PAGE.login].includes(location.pathname) && !isSSOCallback) {
   if (![DEFAULT_ENTER_PAGE.login].includes(location.pathname) && !isSSOCallback) {
     const userInfo = await fetchUserInfo();
     const userInfo = await fetchUserInfo();
     checkDefaultPage(userInfo);
     checkDefaultPage(userInfo);

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

@@ -1,4 +1,4 @@
-import { useEffect, useState } from 'react';
+import { useEffect, useRef, useState } from 'react';
 import { Spin, message } from 'antd';
 import { Spin, message } from 'antd';
 import { history } from 'umi';
 import { history } from 'umi';
 import { request } from 'umi';
 import { request } from 'umi';
@@ -11,10 +11,23 @@ import { DEFAULT_ENTER_PAGE } from '@/config/settings';
  */
  */
 const SSOCallback = () => {
 const SSOCallback = () => {
   const [loading, setLoading] = useState(true);
   const [loading, setLoading] = useState(true);
+  const processedRef = useRef(false);
 
 
   useEffect(() => {
   useEffect(() => {
     const exchangeCode = async () => {
     const exchangeCode = async () => {
-      const params = new URLSearchParams(window.location.search);
+      // 防止重复执行
+      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 code = params.get('code');
       const error = params.get('error');
       const error = params.get('error');
 
 
@@ -49,8 +62,8 @@ const SSOCallback = () => {
 
 
           message.success('登录成功');
           message.success('登录成功');
 
 
-          // 跳转首页
-          history.push(DEFAULT_ENTER_PAGE.user);
+          // 跳转首页 - 使用 replace 避免 back 回到 callback
+          history.replace(DEFAULT_ENTER_PAGE.user);
         } else {
         } else {
           message.error(result.message || '登录失败');
           message.error(result.message || '登录失败');
           history.push(DEFAULT_ENTER_PAGE.login);
           history.push(DEFAULT_ENTER_PAGE.login);