Next.js中如何向getServerSideProps添加请求头或自定义请求参数?
首先明确前提:getServerSideProps 仅在页面请求阶段运行,分为两种场景:首次硬加载/直接输入地址访问、站内客户端导航(通过next/link或next/router跳转)。你存在客户端内存state中的JWT仅在页面完成客户端渲染后才存在,因此首次硬加载场景下无法直接将内存中的JWT传给getServerSideProps,仅客户端导航场景可以实现不依赖cookie、查询参数传值。
方案1:拦截Next.js客户端数据请求,注入自定义请求头
该方案完全符合你将JWT放到请求头的需求,无需使用cookie也不需要修改查询参数:
- 在全局
_app.js/_app.tsx中拦截原生fetch请求,匹配Next.js内部调用getServerSideProps的请求路径(固定格式为/_next/data/*/*.json),给匹配的请求新增自定义Authorization头,传入内存中存储的JWT
示例拦截代码:import { useEffect } from 'react' import { useRouter } from 'next/router' function MyApp({ Component, pageProps }) { const router = useRouter() // 假设你的JWT存在全局state中,这里替换为你实际的JWT变量 const jwt = pageProps.userJwt useEffect(() => { const originalFetch = window.fetch window.fetch = async (input, init = {}) => { // 仅匹配Next.js客户端导航时获取getServerSideProps数据的请求 if (typeof input === 'string' && input.startsWith('/_next/data/')) { init.headers = { ...init.headers, 'Authorization': `Bearer ${jwt}` } } return originalFetch(input, init) } // 组件卸载时恢复原生fetch,避免污染全局环境 return () => { window.fetch = originalFetch } }, [jwt]) return <Component {...pageProps} /> } export default MyApp - 在目标页面的
getServerSideProps中直接从请求头提取JWT即可:export async function getServerSideProps(context) { const authHeader = context.req.headers.authorization const jwt = authHeader ? authHeader.replace('Bearer ', '') : null // 这里就可以用拿到的JWT发起服务端请求 const userData = await fetch('你的业务接口地址', { headers: { Authorization: `Bearer ${jwt}` } }).then(res => res.json()) return { props: { userData } } } - 局限性:仅支持站内客户端导航场景,用户硬刷新页面、或直接在地址栏输入目标页面地址访问时,客户端拦截逻辑还未运行,且内存中的JWT还未初始化,无法拿到自定义请求头。
方案2:临时缓存中转传值
如果你需要同时兼容硬刷新场景,又不想把JWT直接暴露在查询参数中,可以用一次性临时凭证中转:
- 客户端跳转前,先将内存中的JWT发送到你自己实现的一个临时存值接口,接口生成一个随机、10秒内有效的一次性key,将key和JWT的映射关系存储到Redis或服务端内存缓存中
- 跳转目标页面时仅在查询参数携带这个一次性key,JWT本身不会出现在地址栏
- 在
getServerSideProps中拿到查询参数里的key后,到缓存中取出对应的JWT,取出后立刻删除缓存中的映射关系,避免重复使用 - 优势:JWT不会明文暴露,同时兼容客户端导航和硬刷新场景
全场景兼容方案说明
如果你需要支持所有访问场景(包括用户直接输入地址访问、书签打开页面),最稳妥的实现方式还是将JWT存储到带HttpOnly、Secure、SameSite属性的Cookie中,服务端可以直接从context.req.cookies中读取,不存在XSS风险,也不需要额外做适配。
内容的提问来源于stack exchange,提问作者anvin
相关产品推荐
相关产品推荐

