|
|
@@ -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 || '登录失败');
|