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

Next.js getServerSideProps访问localStorage及JWT鉴权方案咨询

一、现有鉴权方案的设计缺陷

  • 鉴权覆盖场景不全:你当前从req.body读取token的逻辑,仅能覆盖带请求体的POST/PUT等类别的数据请求,所有GET类请求(包括页面初始访问、路由跳转、静态资源加载)没有请求体,middleware完全拿不到token,会直接出现鉴权逻辑漏判。
  • 执行逻辑存在运行时矛盾:middleware和getServerSideProps都运行在服务端环境,根本没有权限访问客户端的localStorage,你设计的「校验不通过则清除localStorage中token」的逻辑在服务端完全无法执行,最终会出现用户已经被重定向到登录页,但本地localStorage里的失效token仍然残留,下次访问重复触发校验失败、重定向的死循环问题。
  • 鉴权边界设计错误:你把鉴权触发点绑定在「发起数据库请求」节点,意味着所有不需要查库的受保护路由完全处于裸奔状态,未登录用户可以直接访问这类页面,达不到路由级访问控制的要求。
  • token传递方式不规范:将token放在请求体中传递,不符合通用鉴权规范,会遇到文件上传、form表单提交等场景请求体被占用、跨域请求漏传body、代理层/日志明文截获body内容等问题,稳定性和安全性都不足。

二、SSR场景下的身份校验实现方案

核心前提:服务端运行时不存在浏览器API,无法读取localStorage,因此需要将鉴权凭证存储在浏览器会自动随每次请求携带的介质中,也就是Cookie,从根源解决服务端拿不到凭证的问题,不需要依赖客户端useEffect发请求二次校验,就能实现完整的服务端渲染鉴权。

具体实现步骤

  • 调整token存储逻辑
    用户登录接口校验通过后,不要将JWT返回给前端存入localStorage,而是直接通过响应头Set-Cookie将token写入Cookie,同时给Cookie加上HttpOnly、Secure(生产环境必填)、SameSite=Lax、Path=/属性:

    HttpOnly属性标记的Cookie无法被客户端JS读取,能彻底规避XSS攻击窃取token的风险,安全性远高于localStorage存储方案。
    配置完成后,不管是用户首次访问页面的服务端渲染请求,还是客户端路由跳转的请求,浏览器都会自动将Cookie携带在请求头中,middleware和getServerSideProps可以直接从请求对象上解析到token,不需要客户端手动传递。

  • 抽离通用鉴权工具方法
    把token解析、校验的逻辑抽成独立的公共方法,避免重复编码:
    // utils/auth.js
    const jwt = require('jsonwebtoken')
    
    module.exports = function getAuthUser(req) {
      // 直接从请求附带的cookie中取token
      const token = req.cookies?.auth_token
      if (!token) return null
      try {
        // 用服务端存储的密钥校验token合法性
        const userInfo = jwt.verify(token, process.env.JWT_SECRET)
        return userInfo
      } catch (err) {
        //  token过期、签名不合法都直接返回未登录状态
        return null
      }
    }
    
  • 在getServerSideProps中完成校验与渲染
    受保护的页面在getServerSideProps阶段调用上述鉴权方法,校验失败则先清除失效Cookie,再返回重定向响应;校验通过则正常查询页面数据,连同用户信息一起作为props传给页面完成服务端渲染:
    // pages/protected-page.js
    const getAuthUser = require('../utils/auth')
    
    export async function getServerSideProps(context) {
      const user = getAuthUser(context.req)
      if (!user) {
        // 先清除失效的鉴权cookie
        context.res.setHeader(
          'Set-Cookie',
          'auth_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
        )
        // 重定向到登录页
        return {
          redirect: {
            destination: '/login',
            permanent: false,
          }
        }
      }
      // 校验通过,正常查询页面渲染所需的服务端数据
      // const pageData = await db.query(...)
      return {
        props: {
          user,
          // ...pageData
        }
      }
    }
    
    export default function ProtectedPage({ user }) {
      // 直接拿服务端返回的数据渲染,不需要客户端再做校验
      return <div>当前登录用户:{user.name}</div>
    }
    
  • 可选优化:全局middleware统一拦截
    对于有大量受保护路由的应用,可以在根middleware中配置路由匹配规则,对受保护路由统一做token校验,不需要每个页面单独写鉴权逻辑,校验不通过直接返回重定向+清Cookie的响应,减少重复代码的同时提升响应速度。

注意事项

  • 绝对不要在getServerSideProps、middleware这类服务端代码中尝试访问window、localStorage等浏览器API,运行时会直接报错。
  • JWT的签名密钥必须存储在服务端环境变量中,绝对不能泄露到客户端代码里。
  • 如果需要兼容存量localStorage存储token的用户,可以在客户端_app的首次加载逻辑中加一层判断:如果localStorage中存在有效token、但Cookie中没有对应凭证,就发一次接口请求将token同步写入Cookie,后续完全走Cookie鉴权流程即可,长期建议彻底废弃localStorage存鉴权凭证的方案。
  • 鉴权失败重定向时必须同步清除失效Cookie,避免残留的无效token导致重复校验失败、循环重定向的问题。

内容的提问来源于stack exchange,提问作者Vraj Solanki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:24:13