176 lines
4.3 KiB
TypeScript
176 lines
4.3 KiB
TypeScript
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
|
|
import { User, AuthState } from '../../types/auth';
|
|
import {
|
|
getToken,
|
|
getUser,
|
|
saveToken,
|
|
saveUser,
|
|
clearAuth,
|
|
isTokenExpired,
|
|
refreshAuthToken,
|
|
generateToken,
|
|
} from '../../lib/authStorage';
|
|
|
|
interface AuthContextType {
|
|
authState: AuthState;
|
|
login: (user: User) => void;
|
|
logout: () => void;
|
|
updateUser: (user: User) => void;
|
|
checkAuth: () => boolean;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
|
const [authState, setAuthState] = useState<AuthState>({
|
|
isAuthenticated: false,
|
|
user: null,
|
|
token: null,
|
|
refreshToken: null,
|
|
});
|
|
|
|
// 初始化时检查登录状态
|
|
useEffect(() => {
|
|
const initAuth = async () => {
|
|
const token = getToken();
|
|
const user = getUser();
|
|
|
|
if (token && user) {
|
|
// 检查token是否过期
|
|
if (isTokenExpired()) {
|
|
// 尝试刷新token
|
|
const refreshed = await refreshAuthToken();
|
|
if (refreshed) {
|
|
setAuthState({
|
|
isAuthenticated: true,
|
|
user,
|
|
token: refreshed.token,
|
|
refreshToken: refreshed.refreshToken,
|
|
});
|
|
} else {
|
|
// 刷新失败,自动使用默认账号登录
|
|
await autoLoginWithDefaultAccount();
|
|
}
|
|
} else {
|
|
setAuthState({
|
|
isAuthenticated: true,
|
|
user,
|
|
token,
|
|
refreshToken: getToken(),
|
|
});
|
|
}
|
|
} else {
|
|
// 没有登录信息,自动使用默认账号登录
|
|
await autoLoginWithDefaultAccount();
|
|
}
|
|
};
|
|
|
|
// 自动登录默认账号
|
|
const autoLoginWithDefaultAccount = async () => {
|
|
// 动态导入避免循环依赖
|
|
const { validatePasswordLogin } = await import('../../lib/authStorage');
|
|
|
|
// 使用默认管理员账号自动登录
|
|
const result = await validatePasswordLogin('admin', 'admin123', 'AUTO');
|
|
|
|
if (result.success && result.user) {
|
|
const newToken = generateToken();
|
|
const newRefreshToken = generateToken();
|
|
|
|
saveToken(newToken, newRefreshToken);
|
|
saveUser(result.user);
|
|
|
|
setAuthState({
|
|
isAuthenticated: true,
|
|
user: result.user,
|
|
token: newToken,
|
|
refreshToken: newRefreshToken,
|
|
});
|
|
} else {
|
|
// 自动登录失败,显示登录页面
|
|
setAuthState({
|
|
isAuthenticated: false,
|
|
user: null,
|
|
token: null,
|
|
refreshToken: null,
|
|
});
|
|
}
|
|
};
|
|
|
|
initAuth();
|
|
}, []);
|
|
|
|
// 定期检查token有效性
|
|
useEffect(() => {
|
|
if (!authState.isAuthenticated) return;
|
|
|
|
const interval = setInterval(async () => {
|
|
if (isTokenExpired()) {
|
|
const refreshed = await refreshAuthToken();
|
|
if (refreshed) {
|
|
setAuthState(prev => ({
|
|
...prev,
|
|
token: refreshed.token,
|
|
refreshToken: refreshed.refreshToken,
|
|
}));
|
|
} else {
|
|
logout();
|
|
}
|
|
}
|
|
}, 5 * 60 * 1000); // 每5分钟检查一次
|
|
|
|
return () => clearInterval(interval);
|
|
}, [authState.isAuthenticated]);
|
|
|
|
const login = (user: User) => {
|
|
const token = generateToken();
|
|
const refreshToken = generateToken();
|
|
|
|
saveToken(token, refreshToken);
|
|
saveUser(user);
|
|
|
|
setAuthState({
|
|
isAuthenticated: true,
|
|
user,
|
|
token,
|
|
refreshToken,
|
|
});
|
|
};
|
|
|
|
const logout = () => {
|
|
clearAuth();
|
|
setAuthState({
|
|
isAuthenticated: false,
|
|
user: null,
|
|
token: null,
|
|
refreshToken: null,
|
|
});
|
|
};
|
|
|
|
const updateUser = (user: User) => {
|
|
saveUser(user);
|
|
setAuthState(prev => ({
|
|
...prev,
|
|
user,
|
|
}));
|
|
};
|
|
|
|
const checkAuth = (): boolean => {
|
|
return authState.isAuthenticated && !isTokenExpired();
|
|
};
|
|
|
|
return (
|
|
<AuthContext.Provider value={{ authState, login, logout, updateUser, checkAuth }}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useAuth() {
|
|
const context = useContext(AuthContext);
|
|
if (context === undefined) {
|
|
throw new Error('useAuth must be used within an AuthProvider');
|
|
}
|
|
return context;
|
|
}
|