Firebase Functions中API密钥及敏感凭据安全存储方案咨询
问题
我有一个使用GoogleAuth访问androidpublisher的Firebase可调用函数,要完成请求认证,需要用到包含敏感信息的service-account-google-play.json文件里的数据。
现在的问题是,这个文件该存在哪?目前我把它放在部署到Firebase的functions文件夹里,但感觉这样不安全。
我考虑过把private_key这类必要变量存到.env文件里,但听说这样也不安全(是真的吗?)。
我了解过Cloud Secrets这类服务,但不想为这种本该免费的功能付费。
请问不使用Cloud Secrets的话,该怎么存储我的API密钥?
代码示例
exports.verifyPurchaseAndroid = async ({payload, authUser, firestore}) => { try { const pathGoogleServiceAccount = process.env.GOOGLE_APPLICATION_CREDENTIALS; // path to json which resides inside the same directory as this function const jsonGoogleServiceAccount = await ReadFile(pathGoogleServiceAccount); const auth = new google.auth.GoogleAuth({ credentials: { client_email: jsonGoogleServiceAccount.client_email, private_key: jsonGoogleServiceAccount.private_key, }, scopes: ['https://www.googleapis.com/auth/androidpublisher'], }); const authClient = await auth.getClient(); const packageName = process.env.BUNDLEIDENTIFIER; const productId = payload?.productId; const token = payload?.receiptData; // console.log(authClient); google.options({ auth: authClient }); // packageName,productId,token you can get from request sent from android const purchaseResponse = await google .androidpublisher({ version: 'v3', }).purchases.products.acknowledge({ // The package name of the application the inapp product was sold in (for example, 'com.some.thing'). packageName: packageName, // The inapp product SKU (for example, 'com.some.thing.inapp1'). productId: productId, // The token provided to the user's device when the inapp product was purchased. token: token, // Request body metadata requestBody: { // request body parameters "developerPayload": "my_developerPayload", }, }); console.log(purchaseResponse); } catch(e){ console.log(e) } }
解决方案
用Firebase Functions内置的环境变量存储敏感数据:这是官方推荐的免费方案,环境变量会被加密存储,只有部署后的函数能访问,不会暴露在代码仓库或部署包中。
操作步骤:- 在本地终端执行命令,将service account的关键字段设为环境变量:
注意私钥里的换行符需要用firebase functions:config:set google_play.client_email="你的客户端邮箱" google_play.private_key="你的私钥内容"\\n转义,或者用双引号完整包裹私钥文本。 - 修改函数代码,通过
functions.config()读取变量:const functions = require('firebase-functions'); // ... const { google_play } = functions.config(); const auth = new google.auth.GoogleAuth({ credentials: { client_email: google_play.client_email, private_key: google_play.private_key.replace(/\\n/g, '\n'), // 还原私钥的换行符 }, scopes: ['https://www.googleapis.com/auth/androidpublisher'], });
- 在本地终端执行命令,将service account的关键字段设为环境变量:
绝对不要部署敏感文件:如果本地需要保留
service-account-google-play.json或.env,一定要在.gitignore中添加这两个文件名,防止提交到代码仓库。部署时不要把这些文件上传到Firebase,完全依赖环境变量传递数据。关于.env的安全性说明:
.env仅适合本地开发使用,不能用于生产环境。Firebase Functions部署时不会自动加载.env文件,而且如果不小心将.env提交到公开仓库,敏感信息会直接泄露,所以生产环境绝对不能依赖.env。
内容的提问来源于stack exchange,提问作者Preem Palver2
相关产品推荐
相关产品推荐

