如何通过Firebase云函数获取API Token配置Axios实例?及Token存储方案
问题描述
我有一个用于获取Qualtrics数据的Axios实例,原本从Vite的.env文件读取API Token:
const getQualtrics = axios.create({ baseURL: 'https://xx1.qualtrics.com/API/v3/', headers: { 'Content-Type': 'application/json', 'X-API-TOKEN': import.meta.env.VITE_API_TOKEN, }, });
为了部署安全,我改用Firebase云函数返回API Token,云函数代码如下(使用functions文件夹内的.env):
exports.getAPI = functions.https.onCall((data, context) => { return { apiToken: process.env.API_TOKEN, }; });
但我尝试以下方式配置Axios实例时并未生效:
const getAPI = httpsCallable(functions, 'getAPI'); let getQualtrics; getAPI().then(result => { getQualtrics = axios.create({ baseURL: 'https://xx1.qualtrics.com/API/v3/', headers: { 'Content-Type': 'application/json', 'X-API-TOKEN': result.apiToken, }, }); });
请问:
- 正确的Axios实例配置方式是什么?
- 在Firebase中存储第三方API Token供前端使用,是否有更佳方案?
解决方案
一、正确的Axios实例配置方式
你的代码不生效有两个核心原因:一是异步操作时序问题——getAPI()是异步请求,后续使用getQualtrics时它可能还未初始化;二是httpsCallable返回的实际数据在data属性下,直接取result.apiToken会取不到值。
推荐两种解决方式:
方式1:异步封装初始化,确保实例就绪后再使用
const getAPI = httpsCallable(functions, 'getAPI'); let getQualtrics; // 封装初始化逻辑,避免重复请求Token async function initQualtricsAxios() { if (!getQualtrics) { const result = await getAPI(); getQualtrics = axios.create({ baseURL: 'https://xx1.qualtrics.com/API/v3/', headers: { 'Content-Type': 'application/json', 'X-API-TOKEN': result.data.apiToken, }, }); } return getQualtrics; } // 使用示例 async function fetchSurveyList() { const axiosInstance = await initQualtricsAxios(); const response = await axiosInstance.get('/surveys'); return response.data; }
方式2:用请求拦截器动态注入Token(更灵活)
先创建基础实例,通过拦截器在每次请求前自动获取/缓存Token,无需等待初始化完成:
const getAPI = httpsCallable(functions, 'getAPI'); let cachedToken = null; // 创建不带Token的基础实例 const getQualtrics = axios.create({ baseURL: 'https://xx1.qualtrics.com/API/v3/', headers: { 'Content-Type': 'application/json', }, }); // 添加请求拦截器,动态注入Token getQualtrics.interceptors.request.use(async (config) => { if (!cachedToken) { const result = await getAPI(); cachedToken = result.data.apiToken; } config.headers['X-API-TOKEN'] = cachedToken; return config; }); // 直接使用实例即可,拦截器自动处理Token getQualtrics.get('/surveys').then(res => console.log(res.data));
二、Firebase存储第三方API Token的更佳方案
直接返回Token给前端存在泄露风险,推荐以下两种更安全的方案:
方案1:用云函数做API代理(最优)
不让前端接触Token,而是通过云函数间接调用Qualtrics API,Token全程在服务器端:
// 云函数代码 const axios = require('axios'); exports.callQualtricsAPI = functions.https.onCall(async (data, context) => { // 可选:验证用户身份,避免未授权调用 if (!context.auth) { throw new functions.https.HttpsError('unauthenticated', '用户未登录'); } try { const qualtricsInstance = axios.create({ baseURL: 'https://xx1.qualtrics.com/API/v3/', headers: { 'Content-Type': 'application/json', 'X-API-TOKEN': process.env.API_TOKEN, }, }); // 根据前端参数转发请求 const response = await qualtricsInstance({ method: data.method, url: data.url, data: data.body, }); return response.data; } catch (error) { throw new functions.https.HttpsError('internal', '调用Qualtrics API失败', error.message); } });
前端调用示例:
const callQualtricsAPI = httpsCallable(functions, 'callQualtricsAPI'); callQualtricsAPI({ method: 'GET', url: '/surveys' }).then(result => { console.log(result.data); });
优点:Token完全不暴露给前端,还能在云函数中添加权限控制、日志记录等逻辑。
方案2:用Firebase Remote Config存储Token
如果必须让前端获取Token,可以用Remote Config动态管理,支持控制台更新Token:
- 在Firebase控制台的Remote Config中添加参数(如
QUALTRICS_API_TOKEN),值设为你的Token。 - 前端获取参数并初始化Axios:
import { getRemoteConfig, fetchAndActivate } from "firebase/remote-config"; const remoteConfig = getRemoteConfig(); remoteConfig.settings.minimumFetchIntervalMillis = 3600000; // 1小时缓存 async function getQualtricsToken() { await fetchAndActivate(remoteConfig); return remoteConfig.getValue('QUALTRICS_API_TOKEN').asString(); }
优点:无需重新部署即可更新Token,还能设置用户分段、地区限制等访问规则。
内容的提问来源于stack exchange,提问作者psych0groov3
相关产品推荐
相关产品推荐

