Javascript 访问document.cookie返回空字符串,即使在开发人员工具中列出了cookie,且httpOnly标志设置为false
有时*,当访问登录页面中的Javascript 访问document.cookie返回空字符串,即使在开发人员工具中列出了cookie,且httpOnly标志设置为false,javascript,django,reactjs,cookies,httponly,Javascript,Django,Reactjs,Cookies,Httponly,有时*,当访问登录页面中的document.cookie时,我会得到一个空字符串,即使: Cookie列在Chrome和Firefox开发者工具中 我感兴趣的cookie的httpOnly标志设置为false 我感兴趣的cookie路径设置为“/” 期望的行为 我的React单页应用程序(SPA)有一个登录页面,其中包含一个元素,用于向后端发送登录凭据。当接收到来自后端的响应并且身份验证成功时,我检查是否正确设置了身份验证cookie。如果是这种情况,将触发重定向,显示登录用户的内容 实际行为
document.cookie
时,我会得到一个空字符串,即使:
元素,用于向后端发送登录凭据。当接收到来自后端的响应并且身份验证成功时,我检查是否正确设置了身份验证cookie。如果是这种情况,将触发重定向,显示登录用户的内容
实际行为
不幸的是,在类似15%的登录尝试中,document.cookie
返回一个空字符串,该字符串阻止重定向并将用户保留在登录页面上。按F5
不起作用,但在成功登录请求后手动替换url路径(例如,将“www.website.tld/login”更新为“www.website.tld/start”)时,用户将被转发到只供登录用户使用的所需页面
我无法手动复制错误。这似乎只是随机发生的。但是当它发生时,我查看了开发人员控制台,我可以看到所有来自后端的cookie(设置正确)
其他信息
- django服务器正在后端运行
- 使用
响应设置所需的cookie。set_cookie('key','value',secure=False httponly=False,samesite='strict')
- JS libs(axios、react路由器)
- (仅限http)
- (仅限http)
import React,{useState}来自“React”;
从“react router dom”导入{Redirect};
从“axios”导入axios;
/**
*我们正在使用cookies.js读取cookies。
*资料来源:https://github.com/madmurphy/cookies.js
*/
功能项目(sKey){
返回新的RegExp(
“(?:^ |;\\s*)”+
encodeURIComponent(sKey).替换(/[\-\.\+\*]/g,“\\$&”)+
“\\s*\\=”
).test(document.cookie);
}
导出常量登录页面=()=>{
const[isAuthenticated,setIsAuthenticated]=useState(false);
const[username,setUsername]=useState(“”);
const[password,setPassword]=useState(“”);
函数handleSubmit(e){
e、 预防默认值();
函数onSuccess(响应){
//处理响应
// [...]
//有时console.log(document.cookie)返回空字符串
如果(hasItem(“auth_cookie”)){
setIsAuthenticated(真);
}否则{
控制台。警告(“未找到Cookie!”);
}
}
功能失效(错误){
//处理错误
}
常量配置={
标题:新标题({
“内容类型”:“应用程序/json;字符集=UTF-8”,
原点:window.location.Origin
})
};
axios
.post(“/api/login/”,{username,password},conf)
。然后(响应=>{
成功(响应);
})
.catch(错误=>{
失败(错误);
});
}
如果(未经验证){
返回;
}
返回(
handleSubmit(e)}
action=“api/登录”
target=“hiddenFrame”
>
电子邮件
setUsername(e.target.value)}
/>
密码
setPassword(e.target.value)}
/>
提交
);
};
路由(JSX)
从“React”导入React;
从“react router dom”导入{Route,Redirect};
常量RootLayout=()=>{
返回(
);
};
/**
*当用户已经登录时处理重定向的组件
*/
const PublicRoute=({component:ChildComponent,…remainingProps})=>{
让isAuthenticated=hasItem(“auth_cookie”);
返回(
是否已认证?:
}
{…剩下的道具}
/>
);
};
/**
*当用户注销时处理重定向的组件。
*例如,当身份验证cookie过期时。
*/
const privaterout=({component:ChildComponent,…remainingProps})=>{
让isAuthenticated=hasItem(“auth_cookie”);
返回(
!我被认证了(
) : (
)
}
{…剩下的道具}
/>
);
};
常量应用=()=>(
} />
{/*...*/}
);
*我知道,这可能不是一篇文章应该如何开始的…
您遇到了sameSite Cookie的问题。有关说明,请参见:
如果将SameSite设置为Strict,则cookie将仅在第一方上下文中发送。[…]当用户在您的站点上时,cookie将按预期与请求一起发送但是,当通过链接进入您的站点时,例如从另一个站点或通过朋友的电子邮件,在该初始请求中,cookie将不会被发送。当您拥有与功能相关的cookie时,这一点很好,这些功能将始终位于初始导航之后,例如更改密码或进行购买,但对宣传片来说太严格了。如果您的读者跟随链接进入站点,他们希望发送cookie
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>
);