如何在React中获取仅HTTP cookie



我目前正在开发一个MERN堆栈应用程序,我使用的身份验证是JWT,并将其保存在我的cookie中。这就是我在用户登录后发送cookie的方式。

res
.cookie("token", token, {
httpOnly: true,
secure: true,
sameSite: "none",
})
.send();

并且我通过获得";令牌";cookie在我的后端。然而,我用这个应用程序实现了Redux,每次刷新页面时,它都会自动注销。我想要的是在我的前端(React)中检测";令牌";我的浏览器中的cookie,但我无法获取。我尝试过使用npm-js cookie,但仍然无法获取。有什么方法可以获取"令牌";曲奇或者根据我读到的内容使用redux-persistent?请帮忙,谢谢。

正如其他答案所解释的那样,您不能通过JS访问httpOnly cookie。

我个人建议你使用不同的方法。当然,cookie和httpOnly听起来是个好主意,你可能会认为cookie比localStorage好一千倍,但最终,你是将令牌存储在localStorage中还是存储在cookie中都无关紧要。您可能会就cookie与localStorage争论数小时,但两者都有各自的漏洞(例如:cookie:CSRF攻击(https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html),localStorage:XSS)。

现在,虽然理论上你可以在这里使用localStorage,但我并不提倡使用它。我建议你放弃cookie和localStorage,将JWT存储在你的应用程序状态中(无论是使用上下文api、redux等),并将带有身份验证头的JWT与你从前端到后端的所有请求一起发送。当然,您的后端需要验证该令牌。例如,您可以只实现一个身份验证中间件,将其添加到所有需要身份验证的路由中。过期也非常容易,因为您不再需要同步JWT和cookie的过期时间。只需在JWT上设置过期时间,在auth中间件中验证该令牌就会发现这一点。如果你想知道为什么这种方法对CSRF攻击是安全的,请看这里:JWT在浏览器中存储在哪里?如何防范CSRF?

以下是一些好文章,我真的建议你读一读第一篇:https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/https://medium.com/@ryanchenkie_40935/react-authentication-how-store-jwt-in-a-cookie-346519310e81

你不能"httpOnly";是指";JavaScript无法访问它";。

使用Redux-Persist也不能真正帮助您确定您是否仍在登录或会话是否超时。该数据可能在几周前就已被持久化,或者令牌可能已被吊销。

您可以做的最明智的事情是在服务器上设置一个/whoami端点,这只是应用程序初始化时在那里发送请求的第一个操作。关于您的用户的信息返回->太好了,保存并显示它。否则你会得到一个"401未经授权";这意味着用户没有登录并且需要登录

尽管您不能在前端使用httpOnly cookie做任何事情,但肯定有一种方法可以处理前端发送的httpOnly cookie,并从该cookie中提取您的JWT,所有这些都在您的MERN堆栈应用程序的后端。

至于持久化用户和防止"刷新时注销"问题,您必须创建一个useEffect挂钩,不断检查令牌是否存在——我们稍后会讨论。

首先,我建议在后端使用Cors:

const cors = require("cors");
app.use(
cors({
origin: ["http://...firstOrigin...", ...],
credentials: true,
})
);

准备就绪后,在创建httpOnly cookie时设置以下选项。此外,创建一个非httpOnly cookie来跟踪您的httpOnly cookie,该cookie具有相同的到期日期和布尔值,而不是JWT。这将允许您使用"通用cookie"库,并在前端实际读取非httpOnly cookie:

res
.cookie("token", token, {
origin: "http://...firstOrigin..."
expires: // set desired expiration here
httpOnly: true,
secure: true,
sameSite: "none",
})
.cookie("checkToken", true, {
origin: "http://...firstOrigin..."
expires: // same as above
secure: true,
sameSite: "none",
})

创建了一个模仿我们实际"令牌"的"checkToken"cookie后,我们可以使用它来设置状态(useState钩子),并通过useEffect钩子在用户存在且未过期的情况下保持用户。

然而,要正确发送它,我们必须首先指定一些内容。在这个例子中,我将使用axios在前端进行这样的API调用。

请注意,每个API调用的请求头都将包含我们的httpOnly cookie及其内容-我们可以通过打开chrome dev工具的网络选项卡来确认这一点,进行API调用,然后检查;请求报头";对于";Cookie"。。。

const cookies = new Cookies();
const checkToken = cookies.get("checkToken");
const AuthUser = () => {
const [user, setUser] = useState(checkToken);
useEffect(() => {
async function checkToken() {
await axios
.post("http://...yourBackend.../authToken", {
withCredentials: true,    // IMPORTANT!!!
})
.then((res) => {
// handle response - if successful, set the state...
// to persist the user
)}
.catch((err) => {
// handle error
)}
};

checkToken();
}, []);
// Implement your login behavior here
}

一旦完成,我们可以确认我们在后端API调用的请求主体中获得了这样的令牌(无论在哪里处理),在控制台中记录cookie以检查它,然后将cookie的值存储在变量中以启用对所述cookie的验证:

app.post(".../authToken", (req, res) => {
// Get all cookies from request headers
const { cookie } = req.headers;
// Check to see if we got our cookies
console.log(cookie);   

// Handle this as you please
if (cookie == undefined) return;

const token = cookie.split("token=")[1].split(";")[0];   // Yep, it's a string
console.log(token);    // Check to see if we stored our cookie's JWT
// Some middleware:
jwt.verify(token, process.env.TOKEN, (err, user) => {
// if success upon verification,
// issue new 'token' and 'checkToken'
});
});

完成。

请注意,这是一个通用的实现,只是理解httpOnly cookie功能的指南。OP从未提供原始代码。

我希望这能有所帮助。祝你好运。

在使用React/Django 创建的项目上,当改进身份验证工作流的安全性时,我们遇到了类似的问题

问题是:什么地方是存放JWT的最佳场所

经过研究,我们最终实现了Oauth2协议,这里有一篇文章可以帮助您理解如果刷新令牌轮换的逻辑

我们的实施是

  1. 在后端生成2个令牌(访问令牌[短寿命]和刷新令牌[长寿命])
  2. 刷新令牌应该存储在HttpOnly cookie中(正如他们在响应中提到的,JS在客户端无法访问它)
  3. 在前端级别,我们只使用访问令牌,当它过期时,我们会调用后端重新生成另一个访问和刷新
  4. 后端将访问HttpOnly cookie中的刷新令牌,并决定它是否有效以生成新令牌
  5. 如果后端生成新的有效令牌,它会向前端发送访问令牌,并更新Cookie中的刷新令牌

Ps:根据此逻辑,您无法访问前端的刷新令牌,因此当您的访问令牌不再有效时,您会告诉服务器检查存储在HttpOnly Cookie中的刷新令牌(如果它仍然有效),然后重新生成其他有效的令牌

我希望这能激励你

您可以使用Node js和express来创建httponly cookie。要访问需要Authorization标头的受保护资源,您应该在节点中创建一个返回令牌的端点,因为httponly cookie只能从服务器访问。

然后在react中,使用fetchapi调用端点,它返回到token。

相关内容

  • 没有找到相关文章

最新更新