【问题标题】:Accessing Google Cloud Storage From Android OAuth2从 Android OAuth2 访问 Google Cloud Storage
【发布时间】:2012-08-21 07:05:32
【问题描述】:

我正在尝试设计一个应用程序,该应用程序可以从我的 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) {

但整个事情都很丑陋,我想要一个更清洁的解决方案

【问题讨论】:

    标签: android google-api oauth-2.0 google-cloud-storage


    【解决方案1】:

    Google 文档实际上具有很大的误导性。他们没有更新他们的控制台链接(继续要求你寻找“注册应用程序”链接,它不存在),他们的 GCS JAVA api 在 Android 中不起作用(GcsService service = 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();
    

    【讨论】:

    • 哇,2 小时前!以及我想弄清楚的...你能解释一下吗但是你仍然需要身份验证,所以你的数据并不完全在公众视野中;它只能通过您的应用访问。 但是?
    • 如果存储桶为 AllUsers 组设置了读取权限,您可以匿名在 GCS 上运行一些操作,无需任何凭据。以下是相关摘录:“唯一的例外是对允许匿名访问的对象的操作。如果 AllUsers 组具有 READ 权限,则可以匿名访问对象。AllUsers 组包括 Internet 上的任何人。” developers.google.com/storage/docs/authentication
    • Victor n:因为这对我来说是很久以前的事了。您能否让我知道 user3261375 的答案是否对您有所帮助,然后我会将其标记为正确。
    • 瑞恩,确实是正确的。它的要点是使用 GoogleCredential,我相信它可以解决所有困难的部分。之后,它只是常规的 HTTP 请求/响应处理。
    • 不确定我是否误解了,但是...是否建议将私钥/密码直接嵌入到您的 Android 应用程序中?
    【解决方案2】:

    这是我将 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();
    

    【讨论】:

      【解决方案3】:

      我不知道您的具体情况,但您能否将这些文件完全公开,以便下载它们根本不需要授权?

      【讨论】:

      • 我知道我不必使用身份验证,但我的主要目标是学习 Android,而不是完成应用程序。我确实找到了一个更简洁的解决方案,使用 PrivateKey serviceAccountPrivateKey = PrivateKeys.loadFromKeyStore(KeyStore.getInstance("PKCS12"), getResources().openRawResource(R.raw.key), "notasecret", "privatekey", "notasecret");这不需要外部库。但最后我从 Google 云存储迁移到了 Amazon S3,发现它更适合像我这样的“学生”。
      猜你喜欢
      • 1970-01-01
      • 2018-11-06
      • 2017-12-24
      • 2017-11-14
      • 2021-11-14
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多