【问题标题】:HttpOnly Cookies not found in Web Inspector在 Web Inspector 中找不到 HttpOnly Cookie
【发布时间】:2020-08-16 17:44:56
【问题描述】:

我正在为使用 MERN 堆栈构建的网站进行用户身份验证,我决定使用存储为 HttpOnly cookie 的 JWT 令牌。当我使用 Postman 发出请求时,cookie 在响应标头中的“Set-Cookie”字段中发送,但未在 Safari Web Inspector 中发送,如下图所示。在存储选项卡中也没有找到 cookie。

为了调试,我已将我的 React 登录表单简化为提交用户的用户名和密码的按钮

import React from "react";

const sendRequest = async (event) => {
  event.preventDefault();
  let response;

  try {
    response = await fetch("http://localhost:5000/api/user/login", {
      method: "POST",
      body: { username: "Joshua", password: "qwerty" },
      mode: "cors",
      // include cookies/ authorization headers
      credentials: "include",
    });
  } catch (err) {
    console.log(err);
  }
  if (response) {
    const responseData = await response.json();
    console.log(responseData);
  }
};

const test = () => {
  return (
    <div>
      <input type="button" onClick={sendRequest} value="send" />
    </div>
  );
};

export default test;

我在后端使用 express,这是我的 index.js,首先接收所有传入的请求

const app = express();

app.use(bodyParser.json());

app.use("/images", express.static("images"));
app.use((req, res, next) => {
  res.set({
    "Access-Control-Allow-Origin": req.headers.origin,
    "Access-Control-Allow-Credentials": "true",
    "Access-Control-Allow-Headers": "Content-Type, *",
    "Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE",
  });

  next();
});

app.use(cookieParser());

// api requests for user info/ login/signup
app.use("/api/user", userRoutes);

这是登录请求最终定向到的中间件

const login = async (req, res, next) => {
  const { username, password } = req.body;
  let existingUser;
  let validCredentials;
  let userID;
  let accessToken;

  try {
    existingUser = await User.findOne({ username });
  } catch (err) {
    return next(new DatabaseError(err.message));
  }

  // if user cannot be found -> username is wrong
  if (!existingUser) {
    validCredentials = false;
  } else {
    let isValidPassword = false;
    try {
      isValidPassword = await bcrypt.compare(password, existingUser.password);
    } catch (err) {
      return next(new DatabaseError(err.message));
    }

    // if password is wrong
    if (!isValidPassword) {
      validCredentials = false;
    } else {
      try {
        await existingUser.save();
      } catch (err) {
        return next(new DatabaseError(err.message));
      }

      userID = existingUser.id;
      validCredentials = true;

      accessToken = jwt.sign({ userID }, SECRET_JWT_HASH);
      res.cookie("access_token", accessToken, {
        maxAge: 3600,
        httpOnly: true,
      });
    }
  }

  res.json({ validCredentials });
};

额外信息

在登录中间件中,设置了一个 validCredentials 布尔值并返回给客户端。我能够在前端检索此值,因此我认为这不是 CORS 错误。此外,没有抛出任何错误,并且我的网页上所有其他不涉及 cookie 的 API 请求也可以正常工作。

另一个有趣的事情是,尽管 Postman 和 React 代码使用相同的数据(包含 {username:"Joshua", password:"qwerty"} 的 JS 对象),validCredentials 在 Postman 中的计算结果为 true,在网络检查员。它是我数据库中的现有文档,我希望返回的值是 true,在我添加 cookie 之前就是这种情况

我可以知道我做错了什么吗?或者你对我如何解决这个问题有什么建议吗?我是网络开发的初学者

编辑

通过 dave 的回答,我可以在前端收到“Set-Cookie”标头。但是由于某种原因,它没有出现在 Web 检查器的“存储”选项卡中。

这是响应头

这是来自站点的 cookie 通常出现的存储选项卡

【问题讨论】:

    标签: javascript cookies cross-domain backend httponly


    【解决方案1】:

    如果您尝试将请求作为json发送,则需要设置内容类型标头,以及JSON.stringify对象:

    response = await fetch("http://localhost:5000/api/user/login", {
      method: "POST",
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username: "Joshua", password: "qwerty" }),
      mode: "cors",
      // include cookies/ authorization headers
      credentials: "include",
    });
    

    现在你可能得到相当于

    existingUser = User.findOne({ username: undefined})
    

    所以当你这样做时:

    if (!existingUser) {
        validCredentials = false;
    } else { /* ... */ }
    

    你得到了validCredentials = false 块,cookie 被设置在另一个块中。

    【讨论】:

    • 哦,没错!现在“Set-Cookie”标头出现在我的响应标头中,但 cookie 本身并未出现在 Web Inspector 的“存储”选项卡下。你知道可能是什么问题吗?
    • 没有足够的信息来继续那个。 cookie 是否仍会在后续请求中发送,只是没有显示在选项卡中,还是 cookie 实际上没有设置?
    • 是的,cookie 每次都会被发送,validCredentials 的计算结果为 true。如何区分 cookie 未显示和未设置?
    • 如果您执行另一个请求并且它在请求中发送 cookie,那么它就被设置了。我不知道为什么它不会出现在开发工具中,你可能只是找错地方了。
    • 似乎 cookie 工作正常,只是它们没有出现在开发工具中。感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 2015-02-13
    相关资源
    最近更新 更多