Nuxt.js如何仅在服务端获取API数据以保护请求头中的API_TOKEN
NuxtJS 服务端请求带敏感Token的解决方案
完全可以仅在服务端完成带API_TOKEN的请求操作,避免Token泄露到客户端,以下是可直接落地的实现方案:
核心原理
所有携带敏感Token的请求逻辑全部放在仅服务端可执行的上下文里运行,前端只接收最终返回的业务数据,全程接触不到Token值。
推荐方案(全版本通用,无兼容问题):服务端接口代理
你不需要让前端直接请求第三方API,而是在Nuxt内新增一个服务端接口作为中转,第三方API的请求逻辑、Token都放在这个中转接口里处理:
- 先将Token存入环境变量
.env文件,不要硬编码在业务代码中:
MY_API_TOKEN=你的实际Token值
- 配置服务端运行时配置,确保该配置仅服务端可访问:
Nuxt2 配置(nuxt.config.js)
export default { serverRuntimeConfig: { apiToken: process.env.MY_API_TOKEN }, serverMiddleware: [ // 注册服务端中转接口 { path: '/api/mountains', handler: '~/serverMiddleware/api/mountains.js' } ] }
- 编写中转接口代码
/serverMiddleware/api/mountains.js:
const fetch = require('node-fetch') export default async (req, res) => { // 从服务端配置取Token,客户端完全拿不到该值 const { apiToken } = require('@nuxt/config').default.serverRuntimeConfig const apiRes = await fetch('https://api.nuxtjs.dev/mountains', { headers: { 'X-API-KEY': apiToken } }) const mountains = await apiRes.json() res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(mountains)) }
- 前端页面直接请求中转接口即可,无需携带任何Token:
<template> <div> <h1>Data fetched using asyncData</h1> <ul> <li v-for="mountain in mountains" :key="mountain.title"> <NuxtLink :to="{ name: 'mountains-slug', params: { slug: mountain.slug } }" > {{ mountain.title }} </NuxtLink> </li> </ul> </div> </template> <script> export default { async asyncData({ $http }) { // 直接请求本地中转接口,全程不涉及Token const mountains = await $http.$get('/api/mountains') return { mountains } } } </script>
Nuxt3 简化实现
Nuxt3 自带Server Routes能力,实现更简单:
- 将Token存入
.env文件,前缀加NUXT_:
NUXT_API_TOKEN=你的实际Token值
- 编写服务端接口
/server/api/mountains.get.ts:
export default defineEventHandler(async () => { const config = useRuntimeConfig() return await $fetch('https://api.nuxtjs.dev/mountains', { headers: { 'X-API-KEY': config.apiToken } }) })
- 页面直接调用接口:
<script setup> const { data: mountains } = await useFetch('/api/mountains') </script>
轻量方案:仅服务端执行请求逻辑
如果不想写中转接口,可以通过环境判断确保带Token的请求只在服务端运行:
<script> export default { async asyncData({ $http, $config }) { // 仅服务端环境执行带Token的请求 if (process.server) { const mountains = await $http.$get('https://api.nuxtjs.dev/mountains', { headers: { 'X-API-KEY': $config.apiToken } }) return { mountains } } // 客户端直接复用服务端渲染返回的数据,不发起请求 return {} } } </script>
注意:该方案仅适用于页面为首次服务端渲染入口的场景,若用户从其他客户端路由跳转进入当前页面,会出现数据为空的问题,稳定性不如服务端代理方案。
注意事项
- 不要将API_TOKEN存入
publicRuntimeConfig或硬编码在前端代码中,这两类内容都会暴露到客户端。 - 所有带敏感信息的请求逻辑必须仅在服务端上下文中运行。
内容的提问来源于stack exchange,提问作者Aiden Pearce
相关产品推荐
相关产品推荐

