You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React/Next.js客户端组件向服务端组件传递token的方案咨询

客户端组件Token传递至服务端组件的问题(iframe环境下Cookie失效)

我并非React/Next.js开发人员,当前需要将客户端组件Vendas中的token参数传递给服务端组件Home,遇到以下问题:

  • 尝试通过Cookie实现传递,但在Chrome浏览器的iframe环境下失效——已设置Cookie的sameSite: none及secure属性,服务端组件Home仍无法读取到该Cookie。
  • 曾尝试使用localStorage,但由于Home是服务端组件,该方式无法生效;
  • 也曾尝试通过路由query传参,但操作方式有误,且不清楚如何在Home组件中接收参数。

Vendas组件(客户端组件)

"use client";

import { useRouter } from "next/navigation";
import { jwtDecode } from "jwt-decode";
import { useEffect } from "react";
import Lottie from "lottie-react";
import animationData from "@/animations/spinner.json";
import { setCookie } from "nookies";
interface TokenProps {
  PROFILE: string;
  WORKPLACE_ID: string;
  sub: string;
  exp: number;
}

export default function Vendas({
  searchParams,
}: {
  searchParams: { [key: string]: string | string[] | undefined };
}) {
  const token = searchParams.token;

  const router = useRouter();

  useEffect(() => {
    if (token != undefined && typeof token === "string") {
      const decoded = jwtDecode<TokenProps>(token);
      setCookie(undefined, "token", token, {
        maxAge: 60 * 60 * 1,
        sameSite: "none",
        secure: true,
      });

      if (decoded.PROFILE === "GENERAL") {
        router.push(`/vendas-varejo/geral`);
      } else if (decoded.PROFILE === "SELLER") {
        router.push(`/vendas-varejo/vendedor`);
      } else {
        router.push(`/vendas-varejo/loja`);
      }
    } else {
      throw new Error("Token de acesso não encontrado");
    }
  });
  return (
    <div className="flex h-screen items-center justify-center bg-blue-700">
      <div className="flex h-[70%]">
        <Lottie animationData={animationData} />
      </div>
    </div>
  );
}

Home组件(服务端组件)

import { GeneralProps } from "@/@types/vendas-varejo/general";
import { fetcher } from "@/utils/api";
import Body from "./components/Body";
import { jwtDecode } from "jwt-decode";
import { cookies } from "next/headers";

interface TokenProps {
  PROFILE: string;
  WORKPLACE_ID: string;
  sub: string;
  exp: number;
}


export default async function Home() {
  const cookieStore = cookies();
  const token = cookieStore.get("token");
  if (token?.value != undefined && typeof token === "string") {
    const decoded = jwtDecode<TokenProps>(token);
    if (decoded.PROFILE != "GENERAL") {
      throw new Error("Você não tem permissão para acessar esta página");
    }
  }

  async function getData() {
    const data = await fetcher("/retail-sales", {
      token: token?.value,
    });

    return data;
  }

  const data: GeneralProps = await getData();

  return (
    <>
      <h1 className="mx-3 mt-2">
        Última Atualização: {data.lastUpdate}
      </h1>
      <div>
        <Body data={data} token={token?.value} />
      </div>
    </>
  );
}

可行解决方案

1. 修复iframe环境下的Cookie读取问题

iframe环境下Cookie无法读取,除了已设置的sameSite: none和secure,还需确认以下几点:

  • 网站必须运行在HTTPS协议下(secure属性要求Cookie只能在HTTPS环境中传输,本地开发可启用Next.js的HTTPS模式);
  • 检查Cookie的domain设置:如果iframe嵌入的是不同域名,需确保domain设置正确,或不指定domain让浏览器自动处理;
  • 查看Chrome隐私设置:Chrome默认会在部分场景下阻止第三方Cookie,需确保你的站点在用户的允许列表中,或引导用户开启第三方Cookie权限。

2. 路由Query参数传递(修正操作方式)

这种方式适合快速验证,但token会暴露在URL中,存在安全风险,仅建议短期测试或非敏感场景使用。

客户端组件Vendas中传递参数

修改router.push逻辑,将token编码后作为query参数携带:

// 在Vendas组件的useEffect中修改跳转代码
if (decoded.PROFILE === "GENERAL") {
  router.push(`/vendas-varejo/geral?token=${encodeURIComponent(token)}`);
} else if (decoded.PROFILE === "SELLER") {
  router.push(`/vendas-varejo/vendedor?token=${encodeURIComponent(token)}`);
} else {
  router.push(`/vendas-varejo/loja?token=${encodeURIComponent(token)}`);
}

使用encodeURIComponent编码token,避免特殊字符导致的路由解析错误。

服务端组件Home中接收参数

服务端组件可通过searchParams参数直接获取路由query:

// 修改Home组件的定义,接收searchParams参数
export default async function Home({
  searchParams,
}: {
  searchParams: { [key: string]: string | string[] | undefined };
}) {
  const token = searchParams.token as string | undefined;
  
  // 验证token逻辑
  if (token) {
    const decoded = jwtDecode<TokenProps>(token);
    if (decoded.PROFILE !== "GENERAL") {
      throw new Error("Você não tem permissão para acessar esta página");
    }
  }

  async function getData() {
    return await fetcher("/retail-sales", { token });
  }

  const data: GeneralProps = await getData();

  return (
    <>
      <h1 className="mx-3 mt-2">
        Última Atualização: {data.lastUpdate}
      </h1>
      <div>
        <Body data={data} token={token} />
      </div>
    </>
  );
}

3. 客户端中转+Server Action(更安全)

如果不想用Cookie或暴露token在URL中,可通过Server Action实现安全传递:

  1. 在服务端创建一个Server Action,接收token并返回所需数据;
  2. 在客户端组件中调用该Action,传入token;
  3. 服务端组件改为客户端组件,或通过客户端组件渲染数据。

这种方式避免了token暴露,且适配iframe环境,但需要调整组件结构。


内容的提问来源于stack exchange,提问作者Victor Lindberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 04:14:59