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

如何限制获取Google Maps API密钥的后端接口访问权限?

问题

我的Web应用采用React前端+Node.js(Express)后端架构,集成了react-google-maps地图组件,该组件依赖于在Google Cloud控制台创建的API密钥。我已开发后端接口用于获取所需的API密钥,当前该功能可正常工作:请求成功后密钥会传入APIProvider,地图也能正常显示,且密钥未直接暴露在前端代码中。

但通过开发者工具的Network面板,可查看到后端请求的接口地址https://examplesite/fetchApiKey,直接在浏览器中访问该URL就能以JSON格式获取到API密钥。请问如何限制该接口的访问权限?

我已在GCP的“APIs and Services > Credentials”中设置了应用限制,确保密钥仅能被我的前端网站使用,这在一定程度上可防止滥用,但我希望能完全隐藏密钥。

我猜测需要在Cloud Run Functions的权限设置中操作,但仅能修改特定Google账号的权限;尝试设置Cloud Run的“Ingress”和“Authentication”可限制访问,但不知如何授权我的网站调用该接口。

前端代码片段

export function SokArrangement() {

  const [apiKey, setApiKey] = useState<string | null>(null);
  fetch('https://examplesite/fetchApiKey')
  .then(res => res.json())
  .then(data => {
    setApiKey(data.apiKey);
  });

... //other code

  return(
  ... //other code
  <APIProvider apiKey={apiKey} onLoad={() => console.log('Maps API has loaded.')}>
    <div style={{ height:"100vh", width:"100%" }}>
      <Map  defaultZoom={13}
        defaultCenter={ mapposition }
        mapId={"7ff7bc8394287bed"}>
        <ClusterMarkers addresses={addresses}/> //Generates various markers
      </Map>
    </div>
  </APIProvider>
  )
}

后端代码片段

import { onRequest } from "firebase-functions/v2/https";
import express from 'express';
import cors from 'cors';

const app = express();
app.use(cors({
  origin: ['https://examplesite']
}));

app.get('/apiKey', (req, res) => {
  res.json({ apiKey: 'aPiKeYsTuFf123456789' });
});

export const getApiKey = onRequest(app);
解决方案

1. 加强请求校验,拦截非法访问

当前的CORS仅限制了请求来源,可以叠加多层校验,拦截直接通过地址栏发起的请求:

修改后端接口逻辑:

app.use(cors({
  origin: ['https://examplesite'],
  credentials: true
}));

app.get('/apiKey', (req, res) => {
  // 校验Referer头,确保请求来自前端页面而非直接访问
  const referer = req.get('Referer');
  if (!referer || !referer.startsWith('https://examplesite/')) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  // 可选:添加自定义请求头校验,进一步过滤非法请求
  const authHeader = req.get('X-App-Auth');
  if (authHeader !== process.env.APP_AUTH_TOKEN) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  res.json({ apiKey: process.env.GOOGLE_MAPS_API_KEY });
});

前端请求时添加自定义头:

fetch('https://examplesite/fetchApiKey', {
  headers: {
    'X-App-Auth': 'your-predefined-token' // 与后端环境变量值一致
  }
})
.then(res => res.json())
.then(data => setApiKey(data.apiKey));

2. 基于用户身份验证限制访问

如果应用有用户登录系统,可借助Firebase Auth验证请求身份,仅允许已登录的合法用户获取密钥:

前端携带ID Token请求

import { getAuth, getIdToken } from "firebase/auth";

// ...

const auth = getAuth();
getIdToken(auth.currentUser)
.then(idToken => {
  return fetch('https://examplesite/fetchApiKey', {
    headers: {
      'Authorization': `Bearer ${idToken}`
    }
  });
})
.then(res => res.json())
.then(data => setApiKey(data.apiKey));

后端验证ID Token

import { getAuth } from "firebase-admin/auth";
import admin from "firebase-admin";

admin.initializeApp();

app.get('/apiKey', async (req, res) => {
  const idToken = req.headers.authorization?.split('Bearer ')[1];
  if (!idToken) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  try {
    await getAuth().verifyIdToken(idToken);
    // 验证通过,返回密钥
    res.json({ apiKey: process.env.GOOGLE_MAPS_API_KEY });
  } catch (error) {
    res.status(403).json({ error: 'Invalid token' });
  }
});

3. 后端代理地图请求,彻底隐藏密钥

完全避免前端接触密钥的最优方案是由后端代理所有地图相关请求:

  • 前端不直接调用Google Maps API,而是将地图操作请求发送到你的后端接口
  • 后端携带密钥调用Google Maps API,处理结果后返回给前端
  • 这种方式需要重构部分地图逻辑,但能从根源上防止密钥泄露

4. 配置Cloud Run Functions访问控制

如果后端部署在Cloud Run(Firebase Functions托管于Cloud Run),可通过以下方式限制访问:

  1. 设置Ingress控制:将Ingress改为"Internal only"或"Allow internal traffic and Cloud Load Balancing",仅允许内部服务或负载均衡的请求访问
  2. 启用身份验证:开启"Require authentication",然后为前端服务(或负载均衡器)添加Cloud Run Invoker角色权限
    • 进入Cloud Run控制台,找到目标函数服务
    • 进入"Permissions"页面,添加对应主体(如项目服务账号、IAP用户组)并授予角色

内容的提问来源于stack exchange,提问作者Åsmund Vassbotn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:53:20