从Android OAuth2访问Google云端存储

Rya*_*ner 9 android google-api oauth-2.0 google-cloud-storage

我正在尝试设计一个从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();
Run Code Online (Sandbox Code Playgroud)

在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) {
Run Code Online (Sandbox Code Playgroud)

但整件事情很难看,我想要一个更清洁的解决方案

use*_*375 10

谷歌文档实际上是误导性的.他们没有更新他们的控制台链接(继续要求你查找"注册应用程序"链接,这是不存在的),他们的GAV的JAVA api在Android中不起作用(GcsService服务= GcsServiceFactory.createGcsService() ).好像他们希望您只从App引擎访问GCS.

所以,这是人们需要做的事情:

  • 您可能不希望用户必须登录GCS或Google(想想Snapchat应用程序).
  • 但您仍然需要身份验证,因此您的数据不完全处于公共视图中; 它只能通过您的应用程序访问.
  • 您希望拥有一个服务帐户P2K文件,您可以将其与应用程序捆绑在一起,这样您的用户就无需在任何地方登录.
  • https://cloud.google.com/console/project,单击项目> API和身份验证>凭据>创建新客户端ID>服务帐户.这样可以下载P2K文件.
  • 将其存储在res/raw/private_key.p2k中,然后使用以下代码验证您的Android应用程序以查询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();
Run Code Online (Sandbox Code Playgroud)

  • 不确定我是否误解了但是......是否建议将私钥/密码嵌入您的Android应用程序中? (3认同)