Next.js中如何访问_app.js渲染组件内的Cookie信息
实现方案
方案1:客户端校验(最简易,适合非httpOnly Cookie场景)
你已经在_app.js中配置了react-cookie的CookiesProvider,直接在Nav组件内调用钩子读取Cookie做判断即可,修改后的代码如下:
import Link from 'next/link'; import { useRouter } from 'next/router'; import axios from 'axios'; import { doOAuthWork } from '../lib/handleDiscordOAuth2'; import { useCookies } from 'react-cookie'; import { useEffect, useState } from 'react'; const Nav = () => { // 替换成你实际存储OAuth令牌的Cookie字段名 const [cookies] = useCookies(['discord_oauth_token']); const [isTokenValid, setIsTokenValid] = useState(false); const [loading, setLoading] = useState(true); useEffect(() => { // 先判断Cookie是否存在 if (!cookies.discord_oauth_token) { setIsTokenValid(false); setLoading(false); return; } // 可选:发请求到后端校验令牌有效性,避免伪造Cookie const verifyToken = async () => { try { // 替换成你的校验接口地址 await axios.get('/api/auth/verify', { withCredentials: true }); setIsTokenValid(true); } catch (e) { setIsTokenValid(false); } finally { setLoading(false); } }; verifyToken(); }, [cookies.discord_oauth_token]); return ( <div className="navbar z-10 top-0 fixed shadow-lg bg-neutral text-neutral-content inset-x-0 bg-opacity-80 backdrop-filter backdrop-blur-lg"> <div className="px-2 mx-2 navbar-start"> <span className="text-lg font-bold"> Status+ </span> </div> <div className="hidden px-2 mx-2 navbar-center lg:flex"> <div className="flex items-stretch"> <div className="btn btn-ghost btn-sm rounded-btn"> <Link href="/"> Home </Link> </div> <div className="btn btn-ghost btn-sm rounded-btn"> <Link href="/"> Status </Link> </div> <div className="btn btn-ghost btn-sm rounded-btn"> <Link href="/"> Dashboard </Link> </div> </div> </div> <div className="navbar-end"> {/* 加载中可渲染占位符,校验通过则不显示登录模块 */} {!loading && !isTokenValid && doOAuthWork()} </div> </div> ); }; export default Nav;
方案2:服务端预取校验(兼容httpOnly Cookie,避免首屏闪烁)
如果你的令牌Cookie设置了httpOnly属性(安全性更高,推荐配置),客户端JS无法读取,可以用_app.js的getInitialProps在服务端拿到Cookie校验后传给组件,修改后的代码如下:
import 'tailwindcss/tailwind.css'; import Head from 'next/head'; import { CookiesProvider } from 'react-cookie'; import Nav from '../components/Nav'; import discordOAuth2 from '../lib/handleDiscordOAuth2'; import cookie from 'cookie'; function MyApp({ Component, pageProps, isAuthValid }) { return ( <CookiesProvider> <> <Head> <title>Next and MDX Blog</title> </Head> <div className="container-fluid mx-auto w-full scrollhost" id="container4"> {/* 将服务端校验结果传给Nav组件 */} <Nav isAuthValid={isAuthValid} /> <main className="scrollhost" id="container2"> <Component {...pageProps} /> </main> </div> </> </CookiesProvider> ); } MyApp.getInitialProps = async ({ ctx }) => { let isAuthValid = false; // 服务端读取请求头中的Cookie if (ctx.req?.headers.cookie) { const cookies = cookie.parse(ctx.req.headers.cookie); const token = cookies.discord_oauth_token; if (token) { // 此处可添加服务端调用OAuth接口校验令牌的逻辑 isAuthValid = true; } } return { isAuthValid }; }; export default MyApp;
注意:getInitialProps会关闭Next.js的自动静态优化,如果你站点大部分是静态页面,优先使用方案1即可。
额外注意点
- 生产环境建议OAuth令牌Cookie设置httpOnly、secure、sameSite属性,避免XSS攻击窃取
- 令牌有效性校验优先走后端接口,不要只在客户端判断Cookie是否存在,避免伪造Cookie绕过校验
内容的提问来源于stack exchange,提问作者FxllenCode
相关产品推荐
相关产品推荐

