Как правильно управлять аутентификацией с помощью Axios и React Context в приложении TypeScript?Javascript

Форум по Javascript
Ответить
Anonymous
 Как правильно управлять аутентификацией с помощью Axios и React Context в приложении TypeScript?

Сообщение Anonymous »

Я создаю приложение React + TypeScript и использую Axios для запросов API. У меня есть AuthProvider, использующий контекст React для управления пользователем и токеном, и я столкнулся с несколькими вопросами и проблемами:
  • Нужно ли мне использовать setToken() при входе пользователя в систему?

    Я не уверен, следует ли мне хранить токен в состоянии после входа в систему и как его следует использовать с перехватчиками Axios.
  • Как обрабатывать общедоступные маршруты, такие как вход/регистрация?

    Мой текущий поставщик аутентификации запускает useEffect для получения текущего пользователя (/auth/authorize) при загрузке приложения, но это приводит к ошибкам при входе/регистрации, поскольку токен еще не существует.

    Как я могу предотвратить запуск этих эффектов на общедоступных страницах, сохраняя при этом выбор пользователя на защищенных страницах?
  • Как безопасно хранить токен?

    Я знаю, что localStorage — это вариант, но я слышал, что он не очень безопасен. Каков рекомендуемый способ безопасного сохранения токена между перезагрузками страницы?
import axios from "axios";
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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»