当前位置: 首页 > 知识库问答 >
问题:

如何在React中获取仅限HTTP的cookie?

柴俊捷
2023-03-14

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

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

我通过在后端获取“令牌”cookie来登录用户。然而,我用这个应用程序实现了Redux,每次我刷新页面时,它都会自动注销。我想要的是在我的前端(React)检测浏览器中的“令牌”cookie,但我无法获取它。我尝试过使用npm js cookie,但仍然无法获得它。有没有办法得到“代币”饼干?或者根据我读到的内容使用redux persist?请帮忙,谢谢。

共有3个答案

池恩
2023-03-14

尽管您无法对前端的httpOnly cookie执行任何操作,但肯定有一种方法可以处理前端发送的httpOnly cookie并从该cookie中提取您的JWT,所有这些都在您的MERN堆栈应用程序的后端。

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

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

const cors = require("cors");

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

准备就绪后,在创建httpOnly cookie时设置以下选项。此外,如果JWT,请创建一个非httpOnly cookie,以相同的到期日期和布尔值跟踪您的httpOnly cookie。这将允许您使用“通用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开发工具的网络选项卡来确认这一点,进行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从未提供原始代码。

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

麻超
2023-03-14

你不能。“httpOnly”意味着“JavaScript无法访问它”。

使用Redux Persist也不能真正帮助您确定您是否仍在登录或会话是否超时。这些数据可能在几周前就已经被保存,或者令牌可能已经被撤销。

最明智的做法是在服务器上设置一个/whoamiendpoint,这是应用程序初始化发送请求时的第一个操作。您的用户信息会返回-

吕皓
2023-03-14

正如另一个答案所解释的,你不能通过JS访问httpOnly cookies。

我个人建议你使用不同的方法。当然,cookie和Http听起来只是个好主意,你可能会认为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与认证头一起发送,其中包含您从前端到后端发出的所有请求。当然,您的后端需要验证该令牌。例如,您可以只实现一个atuhentication中间件,将其添加到所有需要身份验证的路由中。过期也很容易,因为你不必再同步JWT和cookie的过期。只需在JWT上设置过期时间,auth中间件中对该令牌的验证就会捕捉到这一点。如果你想知道为什么这种方法对CSRF攻击是安全的,看看这里:JWT在浏览器中的存储位置?如何预防CSRF?

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

 类似资料:
  • 问题内容: 我是python的新手,使用Python Flask并生成REST API服务。 我想检查发送给客户端的授权标头。 但是我找不到在flask中获取HTTP标头的方法。 感谢获得HTTP标头授权的任何帮助。 问题答案: 行为就像字典一样,因此你也可以像使用任何字典一样获取标头:

  • 问题内容: 我用非常熟悉的,但新。 我要检测中的上一页URL ? 问题答案: 您可以使用以下组件传递状态: 然后,您可以从下一页访问。

  • 问题内容: 我刚刚开始使用React.js,但不确定是否有一种特殊的方法来获取文本框的值,该方法是在这样的组件中返回的: 问题答案: 如文档中所述,您需要使用 受控输入 。要进行输入 控制, 您需要在其上指定两个道具 - 每次更改输入都会将组件设置为输入的函数 -来自组件的输入值(例如) 例: 更具体地说是关于textarea的- 这里

  • 我正在尝试使用 accessToken 和 refreshToken 实现 JWT 授权。访问令牌和刷新令牌都需要在仅限HTTP的cookie中设置。 我尝试了这段代码,但它没有设置cookie。我在这里使用NestJS框架。 res.send()方法运行良好,我正在获取数据作为响应。如何在此处设置cookie? 这是我的主要内容。ts文件:- 为了获得我正在使用的cookie:-

  • 问题内容: 在Java Web项目中,如何获得(如果可能)URL请求中的“ HTTP锚”部分?例如,当请求URL为http:// localhost:8080 / servlet / page.htm?param1 = value1&param2 = value2#section时, 我希望能够识别该部分。 上面的例子中产生的子 前述 的,在这种情况下:。有没有办法在符号 后 提取URL的一部分?