正在开发一个在Android和iOS环境中集成Google Cloud的语音文本API的项目。浏览提供的示例代码(https://cloud.google.com/speech-to-text/docs/samples)并使其运行。使用它们作为模板将声音添加到我的应用中,但是示例中存在严重危险,特别是在生成AccessToken(以下Android代码段)时:
// ***** WARNING *****
// In this sample, we load the credential from a JSON file stored in a raw resource
// folder of this client app. You should never do this in your app. Instead, store
// the file in your server and obtain an access token from there.
// *******************
final InputStream stream = getResources().openRawResource(R.raw.credential);
try {
final GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
.createScoped(SCOPE);
final AccessToken token = credentials.refreshAccessToken();
可以在本地进行开发和测试,这很好,但是正如注释所示,将凭据文件保存到生产应用程序版本中并不安全。因此,我需要用服务器端点的请求替换此代码。另外,我需要编写将接受请求并传递回令牌的端点。尽管我发现了一些非常有趣的教程,这些教程与Firebase Admin库生成令牌有关,但是我找不到与对GCP api执行类似操作有关的任何内容。
我们会向我指出正确方向的任何建议/文档/示例都将受到赞赏!
注意:服务器端点将是Node.js环境。
对不起,很抱歉,我能够使所有这些协同工作,现在只回头发布了一个极为简化的方法。首先,我在服务器端点项目https://www.npmjs.com/package/google-auth-library上安装了以下库
为了简单起见,在这种情况下,服务器端点缺少任何身份验证/授权等。我将把这部分交给你。我们还将假装从https://www.example.com/token可以访问此端点
期望是,调用https://www.example.com/token将导致响应,该响应带有字符串令牌,数字表示过期以及有关令牌生成方式的一些额外信息:
即:
{"token":"sometoken", "expires":1234567, "info": {... additional stuff}}
同样在此示例中,我使用了一个ServiceAccountKey文件,该文件将存储在服务器上,建议的途径是设置服务器环境变量并自动使用https://cloud.google.com/docs/authentication/production#finding_credentials_automatic,但这是出于示例的目的,并且足够容易进行快速测试。这些文件如下所示:(荣誉系统不会窃取我的私钥)
ServiceAccountKey.json
{
"type": "service_account",
"project_id": "project-id",
"private_key_id": "378329234klnfgdjknfdgh9fgd98fgduiph",
"private_key": "-----BEGIN PRIVATE KEY-----\nThisIsTotallyARealPrivateKeyPleaseDontStealIt=\n-----END PRIVATE KEY-----\n",
"client_email": "project-id@appspot.gserviceaccount.com",
"client_id": "12345678901234567890",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/project-id%40appspot.gserviceaccount.com"
}
因此,这里是一个简单的端点,它吐出一个AccessToken和一个数字,指示令牌何时过期(以便您以后可以调用新的令牌)。
endpoint.js
const express = require("express");
const auth = require("google-auth-library");
const serviceAccount = require("./ServiceAccountKey.json");
const googleauthoptions = {
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
credentials: serviceAccount
};
const app = express();
const port = 3000;
const auth = new auth.GoogleAuth(googleauthoptions);
auth.getClient().then(client => {
app.get('/token', (req, res) => {
client
.getAccessToken()
.then((clientresponse) => {
if (clientresponse.token) {
return clientresponse.token;
}
return Promise.reject('unable to generate an access token.');
})
.then((token) => {
return client.getTokenInfo(token).then(info => {
const expires = info.expiry_date;
return res.status(200).send({ token, expires, info });
});
})
.catch((reason) => {
console.log('error: ' + reason);
res.status(500).send({ error: reason });
});
});
app.listen(port, () => {
console.log(`Server is listening on https://www.example.com:${port}`);
});
return;
});
现在差不多完成了,将以android为例。第一个剪辑将是它最初从设备文件中提取的方式:
public static final List<String> SCOPE = Collections.singletonList("https://www.googleapis.com/auth/cloud-platform");
final GoogleCredentials credentials = GoogleCredentials.fromStream(this.mContext.getResources().openRawResource(R.raw.credential)).createScoped(SCOPE);
final AccessToken token = credentials.refreshAccessToken();
final string token = accesstoken.getTokenValue();
final long expires = accesstoken.getExpirationTime().getTime()
final SharedPreferences prefs = getSharedPreferences(PREFS, Context.MODE_PRIVATE);
prefs.edit().putString(PREF_ACCESS_TOKEN_VALUE, value).putLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, expires).apply();
fetchAccessToken();
现在,我们从互联网上的端点(未显示)获得了令牌,并拥有令牌和过期信息,我们以与在设备上生成令牌相同的方式来处理它:
//
// lets pretend endpoint contains the results from our internet request against www.example.com/token
final string token = endpoint.token;
final long expires = endpoint.expires
final SharedPreferences prefs = getSharedPreferences(PREFS, Context.MODE_PRIVATE);
prefs.edit().putString(PREF_ACCESS_TOKEN_VALUE, value).putLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, expires).apply();
fetchAccessToken();
无论如何,如果有人有类似的需求,希望对您有所帮助。