9

Google クラウド ストレージ アカウントから適切なサウンド ファイルをダウンロードするアプリを設計しようとしています。アプリはユーザー アカウントにはアクセスしませんが、自分のアカウントにはアクセスします。

私の読書は、最も適切なモデルはサービス アカウント https://code.google.com/p/google-api-java-client/wiki/OAuth2#Service_Accountsであると信じるようになりました

残念ながら、開発者は Android での例を提供しないことを決定しました。それらは、 http://samples.google-api-java-client.googlecode.com/hg/storage-serviceaccount-cmdline-sample/instructions.html?r=defaultで動作する単純な Java を使用した良い例を提供します。

これを 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 を使用する必要がありますか? 「サービス アカウント モデル」を使用する必要があります。そこに例はありますか /

ありがとうライアン


更新 なんとか機能させるという目標を達成できましたが、私のソリューションは私にとって扱いにくいと感じており、意図した方法ではないと確信しています

私がしたことは、入力ストリームとして開いた raw/resource として 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) {

しかし、全体が醜いので、よりクリーンなソリューションが欲しい

4

3 に答える 3

10

Google のドキュメントは、実際にはかなり誤解を招くものです。彼らはコンソール リンクを更新していません (存在しない「アプリの登録」リンクを探すように求め続けます)、GCS 用の Java API は Android で動作しません (GcsService service = GcsServiceFactory.createGcsService() ;))。App Engine からのみ GCS にアクセスすることを期待しているようです。

したがって、ここで行う必要があるのは次のとおりです。

  • おそらく、ユーザーが GCS や Google (Snapchat アプリを考えてみてください) にサインインする必要はありません。
  • しかし、それでも認証が必要なため、データが完全に公開されるわけではありません。アプリからのみアクセスできます。
  • ユーザーがどこにもログインする必要がないように、アプリと一緒にバンドルできるサービス アカウント P2K ファイルが必要です。
  • https://cloud.google.com/console/projectから、[Project] > [APIs & Auth] > [Credentials] > [Create new Client ID] > [Service Account] をクリックします。これにより、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();
于 2014-02-01T21:01:09.837 に答える
0

正確な状況はわかりませんが、これらのファイルを完全に公開して、ダウンロードに認証がまったく必要ないようにしていただけませんか?

于 2012-09-22T05:48:50.403 に答える