#javascript #reactjs #react-router #jwt
Вопрос:
На стороне клиента (Реагировать) У меня есть защищенный маршрут, доступ к которому возможен только при входе пользователя в систему.
В задней части (Node.js, Экспресс) Я использую JWT и сохраняю его в файлах cookie — токен доступа и токен обновления для аутентификации пользователя. Срок действия токена доступа истекает каждые 30 секунд, и токен обновления используется для повторного создания токена доступа.
Что я хочу сделать, так это создать защищенный маршрут для пользователя, вошедшего в систему, проверив, присутствуют ли файлы cookie accesToken и refreshtoken или нет, ниже приведен код:
Auth.js
import axios from "axios";
import Cookies from "universal-cookie";
const cookies = new Cookies();
axios.defaults.withCredentials = true;
class Auth {
constructor() {
this.authenticated = false;
}
isAuthenticated() {
const accessToken = cookies.get("authSession");
const refreshToken = cookies.get("refreshTokenID");
if (!accessToken amp;amp; !refreshToken) {
return (this.authenticated = false);
}
if (accessToken amp;amp; refreshToken) {
return (this.authenticated = true);
}
if (!accessToken amp;amp; refreshToken) {
axios
.post("/api/auth/refresh", {
withCredentials: true,
})
.then(function (res) {
console.log(res.data);
// window.location.reload();
})
.catch(function (error) {
console.log(error.response);
});
}
}
}
export default new Auth();
ProtectedRoutes.js
import { Route, Redirect } from "react-router-dom";
import Auth from "./Auth";
const ProtectedRoutes = ({ component: Component, ...rest }) => {
console.log("🔐", Auth.isAuthenticated());
return (
<Route
{...rest}
render={(props) =>
Auth.isAuthenticated() ? (
<Component {...props} />
) : (
<Redirect to="/loginRegister" />
)
}
/>
);
};
export default ProtectedRoutes;
Все работает нормально, я могу войти в систему, срок действия файлов cookie истекает и они создаются заново каждые 30 секунд. За исключением случаев, когда срок действия маркера доступа истекает и создается заново, Auth.isAuthenticated()
возвращается undefined
. Он возвращается true
только в течение первых 30 секунд (т. Е. Только до тех пор, пока не истечет срок действия первого файла cookie доступа), но когда я пытаюсь обновить свою личную страницу, он возвращается обратно на страницу регистрации входа
файлы cookie также присутствуют:
Обновить
Я забыл добавить свой логин и маршрут приватного экрана:
Маршрут
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import LoginRegisterScreen from "../../screens/LoginRegisterScreen/LoginRegisterScreen";
import ProtectedRoutes from "../Protect/ProtectedRoutes";
import PrivateScreen from "../../screens/PrivateScreen/PrivateScreen";
const Body = () => {
return (
<Router>
<Switch>
<ProtectedRoutes exact path="/" component={PrivateScreen} />
<Route exact path="/loginRegister" component={LoginRegisterScreen} />
</Switch>
</Router>
);
};
export default Body;
Логин-манипулятор внутри моего loginRegisterScreen.js
const loginHandler = async (e) => {
e.preventDefault();
console.log("Login hander called");
const config = {
headers: {
"Content-Type": "application/json",
},
};
try {
await axios.post(
"/api/auth/login",
{
email: loginEmail,
password: loginPassword,
},
config
);
history.push("/");
} catch (error) {
setLoginError(error.response.data.error);
setTimeout(() => {
setLoginError("");
}, 5000);
}
};
ОБНОВЛЕНИЕ 2
Оказывается, я все еще вошел в систему, если я ввожу свой личный URL вручную (т. Е. http://localhost:3000/
)в браузере, он позволяет мне получить к нему доступ, просто всякий раз, когда срок действия моего файла cookie истекает Auth.isAuthenticated()
undefined
, и меня возвращают на /loginRegister
маршрут. Что я должен сделать, чтобы сделать это true
вместо undefined
этого .
ОБНОВЛЕНИЕ 3
Добавление изображений для лучшего понимания:
- Сразу после того, как я войду в систему, мой маршрут защиты вступит в действие, и откроется личный экран.
- Через 30 секунд, когда срок действия моего токена доступа истечет, если я обновлю страницу, я вернусь к
/loginRegister
маршруту, потому что некоторые егоAuth.isAuthenticated()
параметры не определены. - Это происходит только тогда, когда я снова набираю URL вручную и ввожу, он переходит на частный маршрут:
ОБНОВЛЕНИЕ 4
Ответ №1:
В Auth.js вы ничего не возвращаете после того, как потребовали новый доступ. Вы можете просто вернуть истину там, как показано ниже;
...
if (!accessToken amp;amp; refreshToken) {
axios
.post("/api/auth/refresh", {
withCredentials: true,
})
.then(function (res) {
console.log(res.data);
return (this.authenticated = true); // <-- this is a new piece of code here
// window.location.reload();
})
.catch(function (error) {
console.log(error.response);
});
}
Комментарии:
1. Спасибо за ответ, я пытался
return (this.authenticated = true)
, но я не знаю, почему он все еще отображаетсяundefined
, он возвращается только тогда, когда я набираю URL вручнуюreturn (this.authenticated = true)
. Я обновил вопрос изображениями, чтобы лучше понять, что происходит.2. Я думаю, вам нужно отладить
isAuthenticated
. Если он все еще не определен, он либо попадает в блок catch, либо не соответствует ни одному из условий if,isAuthentucated
не определен, когда он ничего не возвращает3. @AnkushDogra, вместо
console.log(error.response);
того, чтобы вы могли просто войтиconsole.log(error);
в блок caatch?4. После регистрации я понял
TypeError: this is undefined
, что вы были правы, это зацепит блок,