Аутентификация Google Cloud Speech через GRPC на Android с помощью ключа API

Мне удалось заставить Google Cloud Speech работать в моем приложении для Android, используя учетную запись службы в потоковом режиме через GRPC. Однако, согласно тому, что я прочитал, мне не следует развертывать приложение Android с этими учетными данными в них (которые в настоящее время хранятся в виде файла JSON в ресурсе) по соображениям безопасности. Правильно создать ключ API, как описано здесь: https://cloud.google.com/speech/docs/common/auth

Это позволяет мне ограничить доступ к моему конкретному приложению для Android. Однако мне не удалось узнать, как использовать API-ключ от GRPC. В настоящее время я создаю экземпляр GoogleCredentials из файла JSON, и он отлично работает. Как я могу получить объект учетных данных из ключа API?


person daoudc    schedule 15.10.2016    source источник


Ответы (4)


вы можете попробовать это с помощью ключа API

Metadata.Key<String> API_KEY = Metadata.Key.of("x-goog-api-key", Metadata.ASCII_STRING_MARSHALLER);

Metadata apiKeyMetadata = new Metadata();
apiKeyMetadata.put(API_KEY, yourApiKey);

final ManagedChannel channel = new OkHttpChannelProvider()
    .builderForAddress(HOSTNAME, PORT)
    .nameResolverFactory(new DnsNameResolverProvider())
    .intercept(MetadataUtils.newAttachHeadersInterceptor(apiKeyMetadata))
    .build();
speechStub = SpeechGrpc.newStub(channel);
person Jeongho Ahn    schedule 03.07.2017
comment
применил это, получив android io.grpc.StatusRuntimeException: PERMISSION_DENIED: Запросы от этого клиентского приложения Android ‹empty› заблокированы., есть ли заголовок для пакета приложения? - person dumb_terminal; 22.08.2017
comment
обнаружил, что решение необходимо добавить X-Android-Package и X-Android-Cert. - person dumb_terminal; 22.08.2017
comment
Любопытно, какое значение вы использовали для X-Android-Cert в метаданных для заголовка? Я могу узнать название пакета Android. но не уверен, что это значит? - person Frank; 23.10.2017

Я не могу найти ни одного примера Android. Однако пример клиента iOS устанавливает соединение gRPC с помощью ключа API. Он помещает ключ в заголовок запроса. Вы можете попробовать перевести код iOS на Android.

https://github.com/GoogleCloudPlatform/ios-docs-samples/blob/master/speech/Objective-C/Speech-gRPC-Streaming/Speech/SpeechRecognitionService.m#L59

person Cheuksan Edward Wang    schedule 04.12.2016

Получив токен доступа, вы можете использовать этот метод:

        final GoogleCredentials googleCredentials = new GoogleCredentials(accessToken) {
            @Override
            public AccessToken refreshAccessToken() throws IOException {
                return accessToken;
            }
        }.createScoped(OAUTH2_SCOPES);

Вам необходимо переопределить refreshAccessToken(), поскольку он в настоящее время не поддерживается.

person brandall    schedule 16.10.2016

Вот как это сделать в Котлине. В том числе, как передать пакет и подпись для ограниченного ключа.

    private fun signatureDigest(sig: android.content.pm.Signature): String? {

        val signature: ByteArray = sig.toByteArray()

        return try {
            val md: MessageDigest = MessageDigest.getInstance("SHA1")
            val digest: ByteArray = md.digest(signature)
            BaseEncoding.base16().lowerCase().encode(digest)
        } catch (e: NoSuchAlgorithmException) {
            null
        }
    }

    fun getSignature(pm: PackageManager, packageName: String?): String? {
        return try {
            val packageInfo: PackageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
            if (packageInfo == null || packageInfo.signatures == null || packageInfo.signatures.size === 0 || packageInfo.signatures.get(0) == null) {
                null
            } else signatureDigest(packageInfo.signatures.get(0))
        } catch (e: PackageManager.NameNotFoundException) {
            null
        }
    }

    private fun createConnection() {

        val packageName: String = mActivity.packageName
        val signature = getSignature(mActivity.packageManager, packageName)

        val API_KEY = Metadata.Key.of("X-Goog-Api-Key", Metadata.ASCII_STRING_MARSHALLER)
        val BUNDLE = Metadata.Key.of("X-Android-Package", Metadata.ASCII_STRING_MARSHALLER)
        val SIGN = Metadata.Key.of("X-Android-Cert", Metadata.ASCII_STRING_MARSHALLER)

        val apiKeyMetadata = Metadata()
        apiKeyMetadata.put(API_KEY, "YOUR_API_KEY")
        apiKeyMetadata.put(BUNDLE, packageName)
        apiKeyMetadata.put(SIGN, signature)

        val channel = OkHttpChannelProvider()
                .builderForAddress(HOSTNAME, PORT)
                .nameResolverFactory(DnsNameResolverProvider())
                .intercept(MetadataUtils.newAttachHeadersInterceptor(apiKeyMetadata))
                .build()
        mApi = SpeechGrpc.newStub(channel)
    }
person Waruna    schedule 05.05.2020