如何使用环境变量密钥通过Axios获取数据并保障密钥安全
问题分析与解决方案
核心问题原因
- 客户端无法读取未暴露的环境变量:你的
updateUser.js是客户端组件(useEffect属于客户端执行代码),Next.js默认仅会将带NEXT_PUBLIC_前缀的环境变量暴露给客户端,因此process.env.LOCAL_API_KEY在这里实际是undefined,导致传给后端的密钥参数为空,触发401验证失败。 - 密钥传递方式不安全:即使你给环境变量加上
NEXT_PUBLIC_前缀,将密钥放在URL参数中也会直接暴露在浏览器地址栏、服务器日志、请求历史里,存在严重的泄露风险。
正确实现方案
方案一:利用用户会话替代API密钥验证(推荐)
既然你已经在用useSession(推测是NextAuth.js),直接通过会话验证用户身份,确保当前请求的用户只能访问自己的数据,完全不需要额外传递密钥:
修改后端API路由 [id].js
import db from "@/database/connect" import Users from "@/database/modals/users" import { getServerSession } from "next-auth/next" import { authOptions } from "../auth/[...nextauth]" // 导入你的NextAuth配置文件 export default async function handler(req, res){ const session = await getServerSession(req, res, authOptions) const { id } = req.query // 验证会话有效性,且请求的用户ID与当前登录用户ID一致 if (!session || session.user._id !== id) { return res.status(401).json({ error: 'Unauthorized User..' }) } if (req.method === 'GET') { try{ await db.connect() const userInfo = await Users.findById(id) await db.disconnect() if(userInfo){ // 在后端直接过滤敏感字段,避免前端接触敏感数据 const { password, admin, ...safeUser } = userInfo.toObject() return res.status(200).json({ user: safeUser }) }else{ return res.status(404).json({ error: 'User not found' }) } }catch(err){ return res.status(500).json({ error: 'Failed to fetch user data' }) } }else{ return res.status(405).json({ error: 'ONLY GET REQUESTS ARE ALLOWED' }) } }
修改前端 updateUser.js
const { data: session } = useSession() useEffect(() => { if(session){ const checkUserInfo = async() => { try{ const fetchUserInfo = await axios.get(`/api/users/${session.user?._id}`) localStorage.setItem('userSession', JSON.stringify(fetchUserInfo.data.user)) }catch(err){ console.log(err) localStorage.removeItem('userSession') } } checkUserInfo() }else{ localStorage.removeItem('userSession') } }, [session])
方案二:若需调用第三方Middleware API(后端持有密钥)
如果你的需求是通过自己的API路由调用第三方Middleware API,密钥应该仅在后端存储和使用,前端无需知晓:
import db from "@/database/connect" import Users from "@/database/modals/users" import { getServerSession } from "next-auth/next" import { authOptions } from "../auth/[...nextauth]" import axios from "axios" export default async function handler(req, res){ const session = await getServerSession(req, res, authOptions) const { id } = req.query if (!session || session.user._id !== id) { return res.status(401).json({ error: 'Unauthorized User..' }) } if (req.method === 'GET') { try{ // 后端调用第三方Middleware API,将密钥放在请求头中 const middlewareRes = await axios.get(`https://your-middleware-api.com/users/${id}`, { headers: { 'X-API-Key': process.env.LOCAL_API_KEY // 按第三方要求的头格式传递 } }) const { password, admin, ...safeUser } = middlewareRes.data.user return res.status(200).json({ user: safeUser }) }catch(err){ return res.status(500).json({ error: 'Failed to fetch from middleware API' }) } }else{ return res.status(405).json({ error: 'ONLY GET REQUESTS ARE ALLOWED' }) } }
关键安全注意事项
- 敏感密钥绝不暴露给客户端:客户端代码会被用户完全解析,任何放在前端的密钥都会直接泄露。
- 优先使用会话验证:针对自有API,用户会话(如NextAuth)是最安全的身份验证方式,能精准控制数据访问权限。
- 密钥传递用请求头:若必须传递密钥(如第三方API),使用
Authorization或自定义X-API-Key请求头,禁止放在URL参数或请求体中。 - 环境变量规范:Next.js中仅
NEXT_PUBLIC_前缀的变量会暴露给客户端,敏感变量不要加该前缀,仅在后端使用。
内容的提问来源于stack exchange,提问作者Viper
相关产品推荐
相关产品推荐

