This commit is contained in:
@@ -5,7 +5,6 @@ import { setTokenGetter } from './api-client';
|
||||
const AUTH_API = '/api/auth';
|
||||
|
||||
export default function AuthProvider({ children }: { children: ReactNode }) {
|
||||
const [mode, setMode] = useState<'sso' | 'password'>('sso');
|
||||
const [state, setState] = useState<AuthState>({
|
||||
isLoading: true,
|
||||
isAuthenticated: false,
|
||||
@@ -20,6 +19,8 @@ export default function AuthProvider({ children }: { children: ReactNode }) {
|
||||
setTokenGetter(() => tokenRef.current);
|
||||
|
||||
// 防止 StrictMode 双重调用(jumpToken 一次性使用)
|
||||
if (authStarted.current) return;
|
||||
authStarted.current = true;
|
||||
|
||||
// 监听 401 事件
|
||||
const onUnauthorized = () => {
|
||||
@@ -29,25 +30,14 @@ export default function AuthProvider({ children }: { children: ReactNode }) {
|
||||
};
|
||||
window.addEventListener('auth:unauthorized', onUnauthorized);
|
||||
|
||||
if (!authStarted.current) { authStarted.current = true; authenticate(); }
|
||||
authenticate();
|
||||
|
||||
return () => window.removeEventListener('auth:unauthorized', onUnauthorized);
|
||||
}, []);
|
||||
|
||||
async function authenticate() {
|
||||
let currentMode: 'sso' | 'password';
|
||||
try {
|
||||
const response = await fetch(`${AUTH_API}/config`, { cache: 'no-store' });
|
||||
const config = await response.json();
|
||||
if (!response.ok || !['sso', 'password'].includes(config.mode)) throw new Error();
|
||||
currentMode = config.mode;
|
||||
setMode(currentMode);
|
||||
} catch {
|
||||
setState({ isLoading: false, isAuthenticated: false, user: null, error: '无法获取验证配置,请刷新重试' });
|
||||
return;
|
||||
}
|
||||
// 本地开发免登录开关:.env 里设 VITE_DEV_BYPASS_AUTH=1 启用,仅 dev 生效
|
||||
if (currentMode === 'sso' && import.meta.env.DEV && import.meta.env.VITE_DEV_BYPASS_AUTH === '1') {
|
||||
if (import.meta.env.DEV && import.meta.env.VITE_DEV_BYPASS_AUTH === '1') {
|
||||
setState({
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
@@ -69,15 +59,15 @@ export default function AuthProvider({ children }: { children: ReactNode }) {
|
||||
tokenRef.current = savedToken;
|
||||
// 验证 token 是否仍然有效(尝试请求 health)
|
||||
try {
|
||||
const res = await fetch(`${AUTH_API}/me`, {
|
||||
const res = await fetch('/api/health', {
|
||||
headers: { Authorization: `Bearer ${savedToken}` },
|
||||
});
|
||||
if (res.ok) {
|
||||
const savedUser = await res.json();
|
||||
const savedUser = sessionStorage.getItem('bi_user');
|
||||
setState({
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
user: savedUser,
|
||||
user: savedUser ? JSON.parse(savedUser) : null,
|
||||
error: null,
|
||||
});
|
||||
return;
|
||||
@@ -85,12 +75,6 @@ export default function AuthProvider({ children }: { children: ReactNode }) {
|
||||
} catch { /* token 无效,继续流程 */ }
|
||||
sessionStorage.removeItem('bi_jwt');
|
||||
sessionStorage.removeItem('bi_user');
|
||||
tokenRef.current = null;
|
||||
}
|
||||
|
||||
if (currentMode === 'password') {
|
||||
setState({ isLoading: false, isAuthenticated: false, user: null, error: null });
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 从 URL 提取 jumpToken
|
||||
@@ -135,18 +119,8 @@ export default function AuthProvider({ children }: { children: ReactNode }) {
|
||||
}
|
||||
}
|
||||
|
||||
async function loginWithPassword(password: string) {
|
||||
const response = await fetch(`${AUTH_API}/password`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ password }) });
|
||||
const data = await response.json();
|
||||
if (!response.ok || !data.token) throw new Error(data.message || '登录失败');
|
||||
tokenRef.current = data.token;
|
||||
sessionStorage.setItem('bi_jwt', data.token);
|
||||
sessionStorage.setItem('bi_user', JSON.stringify(data.user));
|
||||
setState({ isLoading: false, isAuthenticated: true, user: data.user, error: null });
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ ...state, mode, loginWithPassword }}>
|
||||
<AuthContext.Provider value={state}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user