NextJS / React - 如何避免对服务器的多次请求?

NextJS / React - how to avoid multiple requests to server?

我正在写一个小项目,其中我对如何设计前端授权流程有疑问。

堆栈是:Next.js/Express/MDB

这是授权问题:在我的应用程序中,有些页面应该只提供给教师。 当应用程序安装时,我会调用我的后端检查存储的 cookie 并授权用户。返回的用户存储在上下文中。

authContext.js

useEffect(() => {
    checkUserLoggedIn();
  }, []);

...

const checkUserLoggedIn = async () => {
    const res = await fetch(`${process.env.NEXT_PUBLIC_CLIENT}/user`);
    const data = await res.json();

    if (res.status === 200) {
      setUser(data.user);
    } else {
      setUser(null);
    }
  };

效果很好。 但现在是我挣扎的部分。 受保护的页面由一个组件包装,该组件再次检查用户是否 a) 已通过身份验证和 b) 已获得授权。

wrapInstructor.js

const CheckInstructor = ({ token, children }) => {
  const [ok, setOk] = useState(false);
  const [login, setLogin] = useState(null);

 useEffect(async () => {
    try {
      const user = await fetch(
        `${process.env.NEXT_PUBLIC_APIURL}/me`,
        {
          method: "GET",
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );
      const { data, error } = await user.json();

      if (error) {
        toast.error("Auf diese Seite können nur eingeloggte User zugreifen");
        setLogin(false);
      }
      if (data && data.role.includes("INSTRUCTOR")) {
        setOk(true);
        setLogin(true);
      }
    } catch (error) {
      toast.error(error);
      setLogin(false);
    }
  }, []);

  return !ok ? (
    <>{login === false ? <NotLoggedIn /> : <Spinner />}</>
  ) : (
    <>{children}</>
  );
};

export default CheckInstructor;

现在问题来了: 当用户将应用程序安装到受保护的路径时,应用程序会同时触发两个身份验证请求。

第一个获得有效响应(来自上下文的请求)。包装器中的第二个获得 304 状态代码,表示自上次请求以来响应没有更改。

但由于包装器需要有效响应,因此受保护页面的内容将不会显示。

我该如何解决这个问题? (注意:我处于开发模式,从本地主机测试)

我的想法是:

  1. 包装器组件不会再次调用服务器 - 上下文中的用户是唯一的真实来源,包装器只检查已存储的用户 --> 问题:这是一个安全做法?用户是否可以操纵商店(React Context 或 Redux),这会使我的应用不安全?

  2. 如果状态代码为 304 并且用户已存储在上下文中,则在包装器组件中还会显示子组件

  3. 在后端编写另一个端点,以便将两个请求发送到不同的路由(我会考虑这种不好的做法,因为 DRY)

我有点迷路了 - 你能帮我理清思绪吗?

非常感谢!

无需访问同一个端点两次来检查用户是否有权访问特定页面。您在身份验证上下文中存储的内容就足够了。只要确保在角色或权限发生变化时更新值即可。

考虑到您的安全问题,您不应认为任何 客户端应用程序是安全的。即使你在每个受保护的页面上添加一个实际的端点调用,仍然有一种方法可以直接调用端点(curl,邮递员,你的名字)。

应该通过在 每个 受保护的 API 路由上引入授权检查来解决该问题。这样你就完全不用担心客户端损坏了。