Java 您的应用程序已使用来自Google Cloud SDK的最终用户凭据进行身份验证,translate.googleapis.com不支持这些凭据

Java 您的应用程序已使用来自Google Cloud SDK的最终用户凭据进行身份验证,translate.googleapis.com不支持这些凭据,java,authentication,google-cloud-platform,google-translate,google-cloud-iam,Java,Authentication,Google Cloud Platform,Google Translate,Google Cloud Iam,阅读类似问题后,如: 及 应用建议的解决方案,我仍然会发现错误: Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden { "code" : 403, "errors" : [ { "domain" : "usageLimits", "message" : "Your application has authenticated us

阅读类似问题后,如:

应用建议的解决方案,我仍然会发现错误:

    Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code" : 403,
  "errors" : [ {
    "domain" : "usageLimits",
    "message" : "Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the translate.googleapis.com. We recommend that most server applications use service accounts instead. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.",
    "reason" : "rateLimitExceeded"
  } ],
  "message" : "Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the translate.googleapis.com. We recommend that most server applications use service accounts instead. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.",
  "status" : "PERMISSION_DENIED"
My pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>seller</groupId>
    <artifactId>home.digest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>home.digest Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://maven.apache.org</url>
    <repositories>
        <repository>
            <id>prime-repo</id>
            <name>Prime Repo</name>
            <url>http://repository.primefaces.org</url>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>6.2</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
            <version>3.0.1.GA</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.1-api -->
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.2.Final</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.6.Final</version>
             <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>2.0.SP1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.as</groupId>
            <artifactId>jboss-as-web</artifactId>
            <version>7.1.1.Final</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.jboss.spec.javax.ejb/jboss-ejb-api_3.2_spec -->
        <dependency>
            <groupId>org.jboss.spec.javax.ejb</groupId>
            <artifactId>jboss-ejb-api_3.2_spec</artifactId>
            <version>1.0.2.Final</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.cloud/google-cloud-translate -->
        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-translate</artifactId>
            <version>1.79.0</version>
        </dependency>
        <dependency>
            <!-- jsoup HTML parser library @ https://jsoup.org/ -->
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.11.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>home.digest</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven 
                defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

此错误消息是由于在设置云SDK时使用用户凭据造成的。通常使用命令
gcloud auth login
完成此操作

有几种方法可以解决这个问题。每个方法都使用一个服务帐户

方法1:

创建服务帐户并设置云SDK以使用该服务帐户

命令示例:

gcloud auth activate-service-account test@development-123456.iam.gserviceaccount.com --key-file=/fullpath/service-account.json
方法2:

将环境变量
GOOGLE\u APPLICATION\u CREDENTIALS
设置为指向您的服务帐户JSON文件

set GOOGLE\u APPLICATION\u CREDENTIALS=/fullpath/service account.json

方法3:

在创建Java SDK客户端时指定服务帐户

此链接显示了指定服务帐户文件的示例:


通常,从GCP运行代码并使用服务帐户是最佳做法。不导出服务帐户密钥也是一种很好的安全实践。所以这个问题已经得到了回答

在这个额外的答案中,我想分享我的见解,问题标题中的错误消息发生在哪里,发生了什么,以及如何设置您的机器以在不导出服务帐户密钥的情况下进行一些本地开发(尽管如此,在测试项目中从一次性serviceaccount导出短期服务帐户密钥对于测试人员来说可能更简单、更好)

我想以为例,sheets API至少需要oauth2作用域
https://www.googleapis.com/auth/spreadsheets.readonly
从电子表格中读取

我的例子是Golang项目

package main
 
import (
    "context"
    "fmt"
    "log"
 
    "google.golang.org/api/option"
    "google.golang.org/api/sheets/v4"
)
 
func main() {
    ctx := context.Background()
 
    // using default authentication, whatever the environment provides. See https://cloud.google.com/docs/authentication#environment-service-accounts
    srv, err := sheets.NewService(ctx, option.WithScopes(sheets.SpreadsheetsReadonlyScope))
    if err != nil {
        log.Fatalf("Unable to retrieve Sheets client: %v", err)
    }
 
    // A sample spreadsheet:
    // https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
    spreadsheetId := "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
    readRange := "Class Data!A2:E"
    resp, err := srv.Spreadsheets.Values.Get(spreadsheetId, readRange).Do()
    if err != nil {
        log.Fatalf("Unable to retrieve data from sheet: %v", err)
    }
 
    if len(resp.Values) == 0 {
        fmt.Println("No data found.")
    } else {
        fmt.Println("got some results, ...")
    }
}
我试图从Google Cloud Shell(GCP内置web云终端)读取一份电子表格,而将我带到这里的完整错误消息是:

googleapi: Error 403: Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the sheets.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/., accessNotConfigured
要通过Google Cloud SDK使用您的用户帐户访问工作表,我们需要具有相应oauth作用域的应用程序默认凭据

$gcloud auth应用程序默认登录--范围=https://www.googleapis.com/auth/spreadsheets.readonly,openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform
我将范围设置为,并添加了电子表格范围。当遵循基于浏览器的身份验证流程时,我被要求允许

Google Auth Library to:

View and manage your data across Google Cloud Platform services

View your Google Spreadsheets
在我的电脑上,代码正在运行

默认情况下,在获取应用程序默认凭据时,如果不指定
--作用域
,则您将只有
通过Google云平台服务查看和管理您的数据的权限
,并且不允许与工作表API对话。如果不指定
--作用域
,在与工作表API对话时,t预期的错误消息是
googleapi:error 403:Request没有足够的身份验证作用域。
。这确实是我在计算机上运行代码时可以观察到的

但是,在Google Cloud Shell上运行代码时,我从问题的标题中得到错误消息,即,
您的应用程序已使用最终用户凭据进行身份验证…
。同时使用相应的
--范围运行
gcloud auth application default login
,不会更改Google Cloud Shell上的此行为。这是因为当代码在Google Cloud Shell上运行时,不会使用应用程序默认凭据

我编写了一些小的调试代码来揭示:

在我的电脑上,运行后

$ gcloud auth application-default login
$ gcloud auth application-default login --scopes=https://www.googleapis.com/auth/spreadsheets.readonly,openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform
我的调试代码打印:

creds uses credentials file? true
token: &oauth2.Token{AccessToken:"...", ..., raw:map[string]interface {}{"access_token":"...", "scope":"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/accounts.reauth https://www.googleapis.com/auth/cloud-platform openid", "token_type":"Bearer"}}
creds uses credentials file? true
token: &oauth2.Token{AccessToken:"...", ..., raw:map[string]interface {}{"access_token":"...", "scope":"https://www.googleapis.com/auth/spreadsheets.readonly https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/accounts.reauth openid https://www.googleapis.com/auth/userinfo.email", "token_type":"Bearer"}}
在我的电脑上,运行后

$ gcloud auth application-default login
$ gcloud auth application-default login --scopes=https://www.googleapis.com/auth/spreadsheets.readonly,openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform
我的调试代码打印:

creds uses credentials file? true
token: &oauth2.Token{AccessToken:"...", ..., raw:map[string]interface {}{"access_token":"...", "scope":"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/accounts.reauth https://www.googleapis.com/auth/cloud-platform openid", "token_type":"Bearer"}}
creds uses credentials file? true
token: &oauth2.Token{AccessToken:"...", ..., raw:map[string]interface {}{"access_token":"...", "scope":"https://www.googleapis.com/auth/spreadsheets.readonly https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/accounts.reauth openid https://www.googleapis.com/auth/userinfo.email", "token_type":"Bearer"}}
我们现在有了
https://www.googleapis.com/auth/spreadsheets.readonly
包括范围

无论我尝试什么,当在Google Cloud Shell上运行调试代码时,我总是得到

creds uses credentials file? false
token: &oauth2.Token{AccessToken:"...", ..., raw:map[string]interface {}{"oauth2.google.serviceAccount":"default", "oauth2.google.tokenSource":"compute-metadata"}}

这意味着Google Cloud Shell上未使用应用程序默认凭据。这是因为Google Cloud Shell上的应用程序默认凭据未写入默认位置
$HOME/.config/gcloud/Application\u Default\u Credentials.json
Google.FindDefaultCredentials()
因此尝试通过GCP元数据服务器进行身份验证。

@John Hanley的回答很有见地,因此我只想添加另一个实例,其中可能会出现此错误或类似错误(在我的案例中也是如此):Firebase CLI。我没有登录任何帐户。执行
Firebase登录
并选择所需的Google帐户足以消除错误

想按照步骤3操作,但想登录GCP sql实例?怎么办?@IndrajeetGour创建了一个包含详细信息的新问题。谢谢!值得一提的是,方法#1对m不起作用e、 方法#2有。@JohnHanley这是否意味着对于某些google API端点(例如
translate.googleapis.com
https://www.googleapis.com/auth/drive
我在尝试呼叫时得到与OP相同的响应)如果不通过
key.json
使用服务帐户进行身份验证,就无法使用它们?(感谢您分享您在这方面的知识和其他问题-非常有用!即)@DBCerigo-服务帐户来自存储在
key.json
中的私钥。我不使用translate或drive API,因此无法发表评论。对于云,大多数应用程序应该使用服务帐户,而不是谷歌帐户(gmail、gsuite、cloud identity等)。对于高级使用,用户帐户可以模拟具有正确角色和设置的服务帐户。如果您的应用程序正在Google服务(计算引擎、应用引擎、云运行、函数等)中运行,则您可以请求元数据服务器提供凭据,而无需进行验证