我正在尝试设计一个从Google云存储帐户下载相应声音文件的应用。该应用不会访问用户帐户,而是访问我自己的帐户。
我的阅读让我相信最合适的模式 服务帐户 https://code.google.com/p/google-api-java-client/wiki/OAuth2#Service_Accounts
不幸的是,开发人员决定不提供Android的示例。它们提供了一个很好的例子,只有普通的Java,它可以工作 http://samples.google-api-java-client.googlecode.com/hg/storage-serviceaccount-cmdline-sample/instructions.html?r=default
我尝试为Android进行调整,但遇到了问题。
GoogleCredential credential =
new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY).setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(STORAGE_SCOPE)
.setServiceAccountPrivateKeyFromP12File(new File("key.p12")).build();
在Google的示例中,他们传递了key.p12文件,但是在Android上,当我将文件放在res / raw文件夹中时,我访问它的唯一方法就是作为输入流。我找不到一种优雅的方式来获取文件传递给JSON。
这一切都让我相信我一定做错了。 我应该使用key.p12吗? 我应该使用“服务帐户模型”吗? 那里有一个例子/
由于 莱恩
更新 我设法实现了让它工作的目标,但我的解决方案对我来说很笨拙,我确信这不是预期的方式
我所做的是将key.p12添加为我打开的原始/资源作为输入流。然后我使用库转换为私钥,如示例中所示。
http://www.flexiprovider.de/examples/ExampleSMIMEsign.html
我的代码看起来像这样
Security.addProvider(new de.flexiprovider.core.FlexiCoreProvider());
// Next, we have to read the private PKCS #12 file, since the the
// private key used for signing is contained in this file:
DERDecoder dec = new DERDecoder(getResources().openRawResource(
R.raw.key));
PFX pfx = new PFX();
try {
pfx.decode(dec);
SafeBag safeBag = pfx.getAuthSafe().getSafeContents(0)
.getSafeBag(0);
PKCS8ShroudedKeyBag kBag = (PKCS8ShroudedKeyBag) safeBag
.getBagValue();
char[] password = "my password from google api".toCharArray();
privKey = kBag.getPrivateKey(password);
new AsyncLoadStorage(this).execute();
} catch (ASN1Exception e) {
但整件事情很难看,我想要一个更清洁的解决方案
答案 0 :(得分:10)
Google文档实际上非常具有误导性。他们没有更新他们的控制台链接(继续要求你查找“注册应用程序”链接,这是不存在的),他们的GAV的JAVA api在Android中不起作用(GcsService服务= GcsServiceFactory.createGcsService() )。好像他们希望您只从App引擎访问GCS。
所以,这是人们需要做的事情:
这对我没有任何问题:
String STORAGE_SCOPE = "https://www.googleapis.com/auth/devstorage.read_write";
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
Log.d("testing", "checking if I can create a credential");
httpTransport = AndroidHttp.newCompatibleTransport();
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(resources_.openRawResource(R.raw.gcs_privatekey),
"password".toCharArray());
PrivateKey key = (PrivateKey) keystore.getKey("privatekey", "password".toCharArray());
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountPrivateKey(key)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton(STORAGE_SCOPE))
// .setServiceAccountUser(SERVICE_ACCOUNT_EMAIL)
// .setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.build();
credential.refreshToken();
String URI = "https://storage.googleapis.com/" + BUCKET_NAME;
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
GenericUrl url = new GenericUrl(URI);
HttpRequest request = requestFactory.buildGetRequest(url);
HttpResponse response = request.execute();
String content = response.parseAsString();
Log.d("testing", "response content is: " + content);
new Storage.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName("appname").build();
答案 1 :(得分:3)
以下是我将inputStream键转换为PrivateKey对象的方法:
PrivateKey serviceAccountPrivateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), MyClass.class.getResourceAsStream("/privatekey.p12"), "notasecret", "privatekey", "notasecret");
// Build service account credential.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(ACCOUNT_ID)
.setServiceAccountScopes(Collections.singleton(StorageScopes.DEVSTORAGE_FULL_CONTROL))
//.setServiceAccountPrivateKeyFromP12File(f)
.setServiceAccountPrivateKey(serviceAccountPrivateKey)
.build();
答案 2 :(得分:0)
我不知道您的具体情况,但您是否可以将这些文件完全公开,以便下载它们时根本不需要验证?