如何在 Google Cloud VM 上正确使用服务账号凭证调用自托管服务

发布时间 - 2026-01-30 00:00:00    点击率:

本文详解为何基于服务账号的 id token 认证无法成功访问 compute engine vm 上的 http 服务,并指出根本原因在于目标受众(target_audience)配置错误——vm 实例本身不自动验证 id token,需自行实现认证逻辑,而当前代码误将 compute engine 当作 cloud run/cloud functions 等托管服务来调用。

Google Cloud Compute Engine 不会自动验证服务账号签发的 ID Token——这与 Cloud Run、Cloud Functions 或 Identity-Aware Proxy(IAP)等托管服务有本质区别。你在代码中使用 IDTokenCredentials.from_service_account_file(...) 并设置 target_audience=f"https://{ip}:{port}",其本意是生成一个用于“向该端点证明身份”的 JWT,但该 JWT 是否被接受、如何校验,完全取决于你部署在 VM 上的应用自身逻辑。而你的 Redis 容器(或后端服务)极大概率并未集成任何 Token 解析与验证流程,因此它直接忽略请求头中的 Authorization: Bearer ,甚至可能因未处理认证中间件而直接超时或拒绝。

换句话说:
✅ 你成功生成了合法的 ID Token;
❌ 但你的 VM 应用没有监听或校验该 Token
⚠️ 因此 ReadTimeout 并非网络不通,而是服务端收到请求后未按预期响应(例如:未读取完整 body、未返回 HTTP 状态码、或认证中间件阻塞且无 fallback)。

正确做法分两类:

✅ 方案一:自行实现 ID Token 校验(推荐用于生产)

在你的容器应用(如 Python Flask/FastAPI 服务)中添加认证中间件,使用 Google Auth 库验证传入的 Authorization: Bearer

# 示例:FastAPI 中间件(需安装 google-auth)
from fastapi import Depends, HTTPException, Request
from google.auth.transport import requests
from google.oauth2 import id_token

async def verify_id_token(request: Request):
    auth_header = request.headers.get("Authorization")
    if not auth_header or not auth_header.startswith("Bearer "):
        raise HTTPException(401, "Missing or invalid Authorization header")

    token = auth_header.split(" ")[1]
    try:
        # 注意:audience 必须与生成 Token 时完全一致(如 https://:8000)
        claims = id_token.verify_token(
            token,
            requests.Request(),
            audience="https://YOUR_VM_PUBLIC_IP:8000"  # 必须严格匹配!
        )
        return claims
    except ValueError as e:
        raise HTTPException(403, f"Invalid token: {e}")

# 使

用示例 @app.post("/get_attributes") async def get_attrs(payload: list, claims: dict = Depends(verify_id_token)): return {"status": "authorized", "user": claims["email"]}
? 关键点:audience 在服务端校验时必须与客户端生成 Token 时的 target_audience 完全一致(协议、IP、端口、路径均需匹配),且服务端必须监听 HTTPS(若用 https://)并配置有效证书(或临时设 verify=False 测试)。

❌ 方案二:放弃 ID Token,改用更轻量认证(开发/测试适用)

若仅需简单访问控制,可改用 API Key、Basic Auth 或双向 TLS,避免复杂 JWT 流程。例如:

# 客户端(发送 API Key)
response = authed_session.post(
    url=url,
    json=uuids,
    headers={"X-API-Key": "your-secret-key"},
    timeout=10  # 建议延长 timeout,避免误判为认证失败
)

服务端校验该 Header 即可,无需依赖 Google Auth。

⚠️ 其他关键注意事项:

  • HTTPS 要求:IDTokenCredentials 默认要求 https:// 开头的 target_audience;若服务跑在 HTTP 上,必须显式使用 http://,且服务端需支持非加密 Token 校验(不推荐生产环境)。
  • 防火墙 ≠ 认证网关:VPC 防火墙规则 0.0.0.0/0 仅控制 IP 层连通性,不提供任何应用层身份认证能力。服务账号绑定防火墙是 IAP 的特性,不适用于裸 VM。
  • 超时设置合理化:将 timeout=2 提升至 timeout=(5, 30)(连接 5 秒 + 读取 30 秒),避免因服务启动慢或 Token 校验耗时导致误报 ReadTimeout。
  • 调试建议:先用 curl -v 手动发送带 Token 的请求,观察服务端日志是否收到请求、是否有解析错误,再逐步排查。

总结:Compute Engine VM 是“空白画布”,所有安全机制(含服务账号认证)需开发者自行落地。盲目复用 Cloud Run 的认证模式必然失败。务必在服务端实现 id_token.verify_token() 校验逻辑,并确保 audience 前后端严格一致——这才是解决 ReadTimeout 的真正钥匙。


# python  # redis  # js  # json  # go  # 防火墙  # app  # 端口  # session  # 后端  # curl  # ai  # proxy  # flask  # 中间件  # fastapi 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何使用.env文件管理环境变量?(最佳实践)  Python3.6正式版新特性预览  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  jQuery validate插件功能与用法详解  如何在IIS7上新建站点并设置安全权限?  香港服务器网站卡顿?如何解决网络延迟与负载问题?  个人网站制作流程图片大全,个人网站如何注销?  实例解析angularjs的filter过滤器  高性价比服务器租赁——企业级配置与24小时运维服务  图册素材网站设计制作软件,图册的导出方式有几种?  浅谈redis在项目中的应用  Android自定义控件实现温度旋转按钮效果  javascript基本数据类型及类型检测常用方法小结  原生JS实现图片轮播切换效果  微信小程序 五星评分(包括半颗星评分)实例代码  利用python获取某年中每个月的第一天和最后一天  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  企业网站制作这些问题要关注  如何用5美元大硬盘VPS安全高效搭建个人网站?  JavaScript如何实现倒计时_时间函数如何精确控制  ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  Laravel如何实现用户密码重置功能?(完整流程代码)  php485函数参数是什么意思_php485各参数详细说明【介绍】  php打包exe后无法访问网络共享_共享权限设置方法【教程】  深圳网站制作平台,深圳市做网站好的公司有哪些?  Laravel如何使用Collections进行数据处理?(实用方法示例)  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  Swift中循环语句中的转移语句 break 和 continue  如何打造高效商业网站?建站目的决定转化率  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  如何快速生成ASP一键建站模板并优化安全性?  Laravel怎么多语言本地化设置_Laravel语言包翻译与Locale动态切换【手册】  node.js报错:Cannot find module 'ejs'的解决办法  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解  购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  北京企业网站设计制作公司,北京铁路集团官方网站?  Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复  LinuxShell函数封装方法_脚本复用设计思路【教程】  php json中文编码为null的解决办法  PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑  Laravel如何构建RESTful API_Laravel标准化API接口开发指南