如何在Google Cloud Run应用中通过IAP获取当前用户邮箱?
在Cloud Run + IAP环境下获取当前用户邮箱
你之前的问题在于用服务账号凭证请求userinfo API,这拿到的是服务账号自身的信息,而非当前访问应用的用户信息。IAP会直接通过请求头或JWT令牌将用户信息传递给你的应用,无需额外调用外部API,以下是两种实现方式:
快速方案:直接读取IAP注入的请求头
当用户通过IAP访问你的Cloud Run应用时,IAP会自动在请求头中注入两个字段:
X-Goog-Authenticated-User-Email: 当前登录用户的邮箱(格式可能为accounts.google.com:user@example.com,需去掉前缀)X-Goog-Authenticated-User-Id: 用户的唯一标识ID
以Python Flask框架为例,直接读取请求头即可:
from flask import Flask, request app = Flask(__name__) @app.route('/') def get_user_email(): raw_email = request.headers.get('X-Goog-Authenticated-User-Email') if raw_email: # 处理邮箱前缀,提取纯邮箱地址 user_email = raw_email.split(':', 1)[1] if raw_email.startswith('accounts.google.com:') else raw_email return f"当前用户邮箱:{user_email}" return "未检测到有效用户信息", 401 if __name__ == '__main__': app.run()
安全方案:验证IAP JWT令牌获取用户信息
直接读取请求头虽然便捷,但存在被伪造的风险。更稳妥的方式是验证IAP签发的JWT令牌,从令牌的payload中提取用户信息:
实现步骤:
- 从请求头的
Authorization字段取出IAP的JWT令牌(格式为Bearer <token>) - 使用Google的公共密钥验证令牌的有效性,确保其由IAP签发
- 解析令牌的payload,提取
email字段
Python示例代码:
import jwt import requests from flask import Flask, request app = Flask(__name__) # 获取IAP验证用的Google公共密钥(建议缓存,避免重复请求) def get_iap_public_keys(): return requests.get('https://www.gstatic.com/iap/verify/public_key').json() @app.route('/') def verify_and_get_user(): auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return "请通过IAP访问应用", 401 iap_token = auth_header.split(' ', 1)[1] public_keys = get_iap_public_keys() try: # 替换为你的Cloud Run服务对应的IAP客户端ID(从GCP控制台IAP设置中获取) YOUR_IAP_CLIENT_ID = 'your-client-id.apps.googleusercontent.com' payload = jwt.decode( iap_token, public_keys, algorithms=['ES256'], issuer='https://cloud.google.com/iap', audience=YOUR_IAP_CLIENT_ID ) user_email = payload['email'] return f"已验证用户邮箱:{user_email}" except jwt.InvalidTokenError as e: return f"令牌验证失败:{str(e)}", 403 if __name__ == '__main__': app.run()
注意事项:
- 你需要从Google Cloud控制台的IAP设置页面,找到对应Cloud Run服务的OAuth客户端ID,替换代码中的
YOUR_IAP_CLIENT_ID - 建议将Google公共密钥缓存到内存或缓存服务中,减少重复请求开销
- 该方案能确保请求确实经过IAP验证,用户信息无法被伪造
内容的提问来源于stack exchange,提问作者Danielle
相关产品推荐
相关产品推荐

