如何在Next.js中实现服务端身份认证,getServerSideProps如何携带token?
服务端数据获取函数携带Token的解决方案
核心问题说明
getServerSideProps、getStaticProps运行在Node.js服务端环境,不存在浏览器的window、document对象,所以无法直接读取localStorage和js-cookie封装的浏览器端Cookie,需要从服务端的请求上下文或者环境变量中获取Token。
分步实现方案
1. 先将Token存入Cookie
首先将原本存在localStorage的Token迁移到Cookie存储,保证Cookie的path设置为/,可以被全站请求携带:
// 浏览器端登录成功后用js-cookie种Cookie import Cookies from 'js-cookie' Cookies.set('auth_token', '实际Token值', { path: '/', maxAge: 86400, // 有效期1天,按需调整 // 如需更高安全性可由后端返回Set-Cookie响应头,设置httpOnly: true防止XSS窃取 })
2. getServerSideProps中读取Cookie携带Token
getServerSideProps的入参自带请求上下文,可直接读取请求头中的Cookie字段,手动解析或者用cookie库解析都可以:
- 先安装
cookie库简化解析:
npm install cookie
- 代码示例:
import cookie from 'cookie' import axios from 'axios' export async function getServerSideProps(context) { // 从请求头解析Cookie const cookies = cookie.parse(context.req.headers.cookie || '') const token = cookies.auth_token // 发请求时携带Token const apiRes = await axios.get('你的接口地址', { headers: { Authorization: `Bearer ${token}` } }) return { props: { data: apiRes.data } } }
3. getStaticProps的适配方案
getStaticProps是构建/增量静态生成阶段运行,不属于单用户请求上下文,无法获取单个用户的个性化Token,分两种场景处理:
- 如果是拉取需要鉴权的公共静态数据:直接将服务端固定鉴权Token存在
.env环境变量中读取即可
export async function getStaticProps() { // 仅服务端可读取的环境变量,不会泄露到前端 const token = process.env.SERVER_STATIC_AUTH_TOKEN const apiRes = await axios.get('公共接口地址', { headers: { Authorization: `Bearer ${token}` } }) return { props: { publicData: apiRes.data }, revalidate: 60 // 按需设置增量更新时间 } }
- 如果是拉取用户个性化数据:不要用
getStaticProps,改用getServerSideProps或者客户端渲染时拉取数据。
优化方案:封装服务端请求实例
避免每次重复写解析逻辑,可以封装专门的服务端axios实例:
// utils/server-axios.js import axios from 'axios' import cookie from 'cookie' export const createServerAxios = (req) => { const cookies = cookie.parse(req.headers.cookie || '') const token = cookies.auth_token return axios.create({ baseURL: '你的接口基础地址', headers: { Authorization: token ? `Bearer ${token}` : '' } }) } // 业务代码中使用 export async function getServerSideProps(context) { const serverAxios = createServerAxios(context.req) const res = await serverAxios.get('/api/user/info') return { props: { userInfo: res.data } } }
内容的提问来源于stack exchange,提问作者Abdelrhman Gad
相关产品推荐
相关产品推荐

