- Нужно ли мне использовать setToken() при входе пользователя в систему?
Я не уверен, следует ли мне хранить токен в состоянии после входа в систему и как его следует использовать с перехватчиками Axios. - Как обрабатывать общедоступные маршруты, такие как вход/регистрация?
Мой текущий поставщик аутентификации запускает useEffect для получения текущего пользователя (/auth/authorize) при загрузке приложения, но это приводит к ошибкам при входе/регистрации, поскольку токен еще не существует.
Как я могу предотвратить запуск этих эффектов на общедоступных страницах, сохраняя при этом выбор пользователя на защищенных страницах? - Как безопасно хранить токен?
Я знаю, что localStorage — это вариант, но я слышал, что он не очень безопасен. Каков рекомендуемый способ безопасного сохранения токена между перезагрузками страницы?
import React, {
createContext,
useContext,
useEffect,
useLayoutEffect,
useState,
} from "react";
type User = {
id: string;
username: string;
email: string;
};
type AuthContextType = {
user: User | null;
token: string | null;
setToken: (token: string | null) => void;
logout: () => void;
};
const AuthContext = createContext(undefined);
export const AuthProvider: React.FC = ({
children,
}) => {
const [token, setToken] = useState(null);
const [user, setUser] = useState(null);
useEffect(() => {
const fetchMe = async () => {
try {
const { data } = await axios.get(
"http://localhost:5000/auth/authorize",
{
withCredentials: true,
},
);
setUser(data.user);
} catch (err) {
setUser(null);
}
};
fetchMe();
}, []);
useLayoutEffect(() => {
const requestInterceptor = axios.interceptors.request.use(
(config) => {
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error),
);
return () => {
axios.interceptors.request.eject(requestInterceptor);
};
}, [token]);
useLayoutEffect(() => {
const responseInterceptor = axios.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
const refreshRes = await axios.post(
"/auth/refreshMyToken",
{},
{ withCredentials: true },
);
setToken(refreshRes.data.token);
return axios(error.config);
}
logout();
return Promise.reject(error);
},
);
return () => {
axios.interceptors.response.eject(responseInterceptor);
};
}, []);
const logout = () => {
setToken(null);
setUser(null);
};
return (
{children}
);
};
// ----- useAuth hook -----
export const useAuth = (): AuthContextType => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};
Подробнее здесь: https://stackoverflow.com/questions/798 ... a-typescri
Мобильная версия