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

如何在Next.js与Cloud Functions中安全解决CORS问题?

安全解决Next.js代理Cloud Functions的CORS问题

问题场景

我在前端使用Next.js,利用其自带的api文件夹提供的服务端Node.js环境搭建代理API,实现前端到Cloud Functions的请求转发,流程如下:

  • 前端向Next.js API发送请求
  • Next.js API向Cloud Functions发送请求
  • 获取响应并返回给前端

但实际运行时出现了CORS跨域问题。

Next.js原代理代码(前端直接调用Cloud Functions)

import { getFunctions, httpsCallable } from 'firebase/functions';
import { firebase } from '@/lib';

export async function deleteUserAccount(userId: string) {
  if (!userId) {
    console.error('deleteUserAccount: 未提供userId');
    return;
  }

  try {
    const functions = getFunctions(firebase, 'us-central1');
    const deleteUserData = httpsCallable(functions, 'deleteUserData');

    const { data }: any = await deleteUserData({
      userId,
    });

    console.log('deleteUserAccount', data);
  } catch (error) {
    console.error('deleteUserAccount error', error);
  }
}

Cloud Functions原实现代码

const admin = require('firebase-admin');
const functions = require('firebase-functions');

exports.deleteUserData = functions.https.onRequest(async (req, res) => {
    const uid = request.auth.uid;
    
    try {
        await admin.auth().deleteUser(uid);
        return { message: 'Data deleted successfully!' };
    } catch (error) {
        console.error('Error deleting user data', error);
        return Promise.reject(error);
    }
});

安全解决方案

核心问题分析

你当前的代码是在前端直接调用Cloud Functions的httpsCallable,相当于绕过了Next.js服务端代理,直接从浏览器发起跨域请求,自然触发CORS限制。正确的做法是将Cloud Functions的调用逻辑放在Next.js的服务端API路由中,让服务端作为中间层转发请求,前端只请求同域的Next.js API,彻底避免CORS问题。

步骤1:重构Next.js服务端API路由

根据你使用的路由方案创建对应的API文件:

  • App Router:app/api/delete-user/route.ts
  • Pages Router:pages/api/delete-user.ts

在文件中实现服务端到Cloud Functions的调用:

import { getFunctions, httpsCallable } from 'firebase/functions';
import { firebase } from '@/lib';
import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  const { userId } = await request.json();
  
  if (!userId) {
    return NextResponse.json({ error: '缺少userId参数' }, { status: 400 });
  }

  try {
    const functions = getFunctions(firebase, 'us-central1');
    const deleteUserData = httpsCallable(functions, 'deleteUserData');
    const { data } = await deleteUserData({ userId });
    
    return NextResponse.json(data);
  } catch (error) {
    console.error('删除用户数据失败:', error);
    return NextResponse.json({ error: '删除失败' }, { status: 500 });
  }
}

步骤2:修改前端代码,请求Next.js API

将原来的前端调用逻辑改为请求自己的Next.js API,不再直接调用Cloud Functions:

export async function deleteUserAccount(userId: string) {
  if (!userId) {
    console.error('deleteUserAccount: 未提供userId');
    return;
  }

  try {
    const response = await fetch('/api/delete-user', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ userId }),
    });

    if (!response.ok) {
      throw new Error('请求失败');
    }

    const data = await response.json();
    console.log('deleteUserAccount', data);
  } catch (error) {
    console.error('deleteUserAccount error', error);
  }
}

步骤3:修复Cloud Functions代码的错误与安全漏洞

原Cloud Functions代码存在语法错误和安全隐患,修正如下:

const admin = require('firebase-admin');
const functions = require('firebase-functions');

// 初始化Firebase Admin(避免重复初始化)
if (!admin.apps.length) {
  admin.initializeApp();
}

exports.deleteUserData = functions.https.onRequest(async (req, res) => {
  // 限制请求方法为POST
  if (req.method !== 'POST') {
    return res.status(405).json({ error: '仅支持POST请求' });
  }

  // 验证用户是否已认证
  if (!req.auth) {
    return res.status(401).json({ error: '未授权访问' });
  }

  const uid = req.auth.uid;
  const { userId } = req.body;

  // 关键安全校验:确保请求删除的用户ID与当前认证用户ID一致,防止越权删除
  if (uid !== userId) {
    return res.status(403).json({ error: '无权限删除该用户' });
  }

  try {
    await admin.auth().deleteUser(uid);
    return res.json({ message: '数据删除成功!' });
  } catch (error) {
    console.error('删除用户数据出错:', error);
    return res.status(500).json({ error: '删除失败' });
  }
});

额外安全建议

  • 开启Cloud Functions身份验证:在Firebase控制台的Cloud Functions设置中,为deleteUserData函数开启“需要身份验证”,确保只有认证用户能调用
  • 添加请求速率限制:在Next.js API路由中集成速率限制库,防止恶意批量请求
  • 避免前端暴露敏感逻辑:所有与Cloud Functions的交互都通过Next.js服务端代理,不直接在前端暴露Firebase配置或函数调用细节

内容的提问来源于stack exchange,提问作者Mark James

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:10:40