Иногда * при доступе к document.cookie
на странице входа в систему я получаю пустую строку, даже если:
- куки перечислены в инструментах разработчика Chrome и Firefox,
- httpТолько флаг повара ie Мне нужно установить значение false,
- путь повара ie Мне нужно установить значение '/'.
Требуемое поведение
Одностраничное приложение My React (SPA) имеет страницу входа, которая содержит элемент <form />
для отправки учетных данных для входа в серверную часть. Когда ответ от бэкэнда получен и аутентификация прошла успешно, я проверяю, правильно ли был установлен повар аутентификации ie. В этом случае будет инициировано перенаправление, в котором будет отображаться контент для зарегистрированных пользователей.
Фактическое поведение
К сожалению, например, 15% попыток входа в систему, document.cookie
возвращает пустую строку, которая предотвращает перенаправление и сохраняет пользователь на странице входа. Нажатие F5
не помогает, но при ручной замене пути URL после успешного запроса на вход в систему (например, обновление 'www.website.tld/ login ' до 'www.website.tld/ start ') пользователь перенаправляется на нужную страницу, предназначенную только для зарегистрированных пользователей.
Я не могу воспроизвести ошибку вручную. Кажется, это происходит случайно. Но когда это происходит и я заглядываю в консоль разработчика, я вижу все куки-файлы из бэкэнда (установлены правильно).
Дополнительная информация
- django сервер работает в бэкэнде
- желаемый повар ie устанавливается с
response.set_cookie('key', 'value', secure=False httponly=False, samesite='strict')
- JS libs (ax ios, response-router)
Похожие:
Страница входа (JSX) )
import React, { useState } from "react";
import { Redirect } from "react-router-dom";
import axios from "axios";
/**
* We're using cookies.js to read cookies.
* Source: https://github.com/madmurphy/cookies.js
*/
function hasItem(sKey) {
return new RegExp(
"(?:^|;\\s*)" +
encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") +
"\\s*\\="
).test(document.cookie);
}
export const LoginPage = () => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
function handleSubmit(e) {
e.preventDefault();
function onSuccess(response) {
// handle response
// [...]
// sometimes console.log(document.cookie) returns empty string
if (hasItem("auth_cookie")) {
setIsAuthenticated(true);
} else {
console.warn("Cookie not found!");
}
}
function onFailure(error) {
// handle error
}
const conf = {
headers: new Headers({
"Content-Type": "application/json; charset=UTF-8",
Origin: window.location.origin
})
};
axios
.post("/api/login/", { username, password }, conf)
.then(response => {
onSuccess(response);
})
.catch(error => {
onFailure(error);
});
}
if (isAuthenticated) {
return <Redirect to="/start" />;
}
return (
<div className="login-page">
<form
name="login-form"
method="post"
onSubmit={e => handleSubmit(e)}
action="api/login"
target="hiddenFrame"
>
<iframe className="invisible-frame" src="" name="hiddenFrame" />
<div>
<label htmlFor="username">Email</label>
<input
name="username"
type="text"
onChange={e => setUsername(e.target.value)}
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
name="password"
type="password"
onChange={e => setPassword(e.target.value)}
/>
</div>
<button type="submit">Submit</button>
</form>
</div>
);
};
Маршрутизация (JSX)
import React from "react";
import { Route, Redirect } from "react-router-dom";
const RootLayout = () => {
return (
<div className="root-layout">
<Switch>
<PublicRoute path="/login" component={LoginPage} />
<PrivateRoute path="/" component={App} />
</Switch>
</div>
);
};
/**
* Component that handles redirection when user is logged in already
*/
const PublicRoute = ({ component: ChildComponent, ...remainingProps }) => {
let isAuthenticated = hasItem("auth_cookie");
return (
<Route
render={props =>
isAuthenticated ? <Redirect to="/" /> : <ChildComponent {...props} />
}
{...remainingProps}
/>
);
};
/**
* Component that handles redirection when user has been logged out.
* E.g. when authentication cookie expires.
*/
const PrivateRoute = ({ component: ChildComponent, ...remainingProps }) => {
let isAuthenticated = hasItem("auth_cookie");
return (
<Route
render={props =>
!isAuthenticated ? (
<Redirect to="/login" />
) : (
<ChildComponent {...props} />
)
}
{...remainingProps}
/>
);
};
const App = () => (
<Switch>
<Route exact path="/" render={() => <Redirect to="/start" />} />
<Route exact path="/start" component={StartPage} />
<Route exact path="/blog" component={BlogPage} />
{/*...*/}
</Switch>
);
* I know, that's probably not how a post should start...