类 Google.Apis.Auth.OAuth2.GoogleCredential.UnderlyingCredential.GetAccessTokenForRequestAsync() 在 Ja

Posted

技术标签:

【中文标题】类 Google.Apis.Auth.OAuth2.GoogleCredential.UnderlyingCredential.GetAccessTokenForRequestAsync() 在 Java 中等效?【英文标题】:class Google.Apis.Auth.OAuth2.GoogleCredential.UnderlyingCredential.GetAccessTokenForRequestAsync() equivalent in Java? 【发布时间】:2022-01-03 22:19:23 【问题描述】:

我已经在 C# 中构建了一个 Azure 函数应用程序,我正在尝试找出 Java 中的 Google.Apis.Auth.OAuth2.GoogleCredential.UnderlyingCredential.GetAccessTokenForRequestAsync() 的等效项,因为我的客户需要我的代码框架一个Java。我需要能够返回 Json Web Token (JWT) 并将其调用到函数内的返回体中。

我发现 Java 类 GoogleCredential 已被贬值,但 Google 的一些产品文档仍然引用它:https://cloud.google.com/java/docs/reference/google-api-client/latest/com.google.api.client.googleapis.auth.oauth2.GoogleCredential。

下面是我用 C# 开发的 sn-p 代码,但我找不到任何类似的方式在 Java 中调用这个类:

using Google.Apis.Auth.OAuth2;

    var cred = GoogleCredential.FromJson(*[myjsonkey]*).CreateScoped(new string[]  "https://www.googleapis.com/auth/analytics.readonly" );
    var token = await cred.UnderlyingCredential.GetAccessTokenForRequestAsync();

Java 类 GoogleCredential 现已完全弃用(链接如下:https://cloud.google.com/java/docs/reference/google-api-client/latest/com.google.api.client.googleapis.auth.oauth2.GoogleCredential#com_google_api_client_googleapis_auth_oauth2_GoogleCredential_createDelegated_java_lang_String_)

任何关于我如何模仿在 Java 中使用等效的 GoogleCredential 类来返回 JWT 的建议或示例都将不胜感激。

更新:我现在明白 com.google.api.client.googleapis.auth.oauth2.GoogleCredential 的替代品现在是 com.google.auth.oauth2.GoogleCredentials,但我不知道如何使用它通过传入从 Azure Key Vault 调用的 json 密钥,以便我可以返回 JWT。这是我到目前为止所构建的,调用 Azure Function key vault 并返回与我的服务帐户关联的 Google .json 机密文件。我收到一条 500 返回消息,因为我在响应中没有适当地调用 JWT。我引用了this part of Google auth library for java,但它不起作用。有什么技巧可以调整我的代码???

 package GetOAuthFunction;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.gson.*;

/**
 * Azure Functions with HTTP Trigger, getting value from Key Vault, returning Google Analytics Access Token in get request return body
 */
public class HttpKeyVaultFunc 
    @FunctionName("GetGoogleAnalyticsOAuthToken")
    public HttpResponseMessage run(
            @HttpTrigger(
                name = "req", 
                methods = HttpMethod.GET, 
                authLevel = AuthorizationLevel.ANONYMOUS) 
            HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) 
        context.getLogger().info("Java HTTP trigger processed a request.");

        String secret = System.getenv("KEY_VAULT_URL");
        SecretClient secretClient = new SecretClientBuilder()
        .vaultUrl(secret)
        .credential(new DefaultAzureCredentialBuilder().build())
        .buildClient();
        
        KeyVaultSecret retrievedSecret = secretClient.getSecret("clientsecret");
        
        String clientsecretvalue = retrievedSecret.getValue();
        JsonObject clientsecretarray = new Gson().fromJson(clientsecretvalue, JsonObject.class);
       GoogleCredentials credentials =  GoogleCredentials.fromStream(clientsecretarray).createScoped(new String "https://www.googleapis.com/auth/analytics.readonly") ;
 
        return request.createResponseBuilder(HttpStatusOK).body("Access Token: "+ credentials.getAccessToken().build());
    

【问题讨论】:

【参考方案1】:

如您所料,Google Auth Library 包含对 Google 服务进行身份验证所需的必要类。

描述Explicit credential loading时请考虑阅读API文档:

要从服务帐户 JSON 密钥中获取凭据,请使用 GoogleCredentials.fromStream(InputStream)GoogleCredentials.fromStream(InputStream, HttpTransportFactory)。笔记 必须在访问令牌之前刷新凭据 可用。

GoogleCredentials credentials = GoogleCredentials.fromStream(new 
FileInputStream("/path/to/credentials.json"));
credentials.refreshIfExpired();
AccessToken token = credentials.getAccessToken();
// OR
AccessToken token = credentials.refreshAccessToken();

在您的代码中,假设您的 Azure Key Vault 包含 JSON 格式的服务帐户凭据,您可以尝试以下操作:

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;
import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.gson.*;

/**
 * Azure Functions with HTTP Trigger, getting value from Key Vault, returning Google Analytics Access Token in get request return body
 */
public class HttpKeyVaultFunc 
    @FunctionName("GetGoogleAnalyticsOAuthToken")
    public HttpResponseMessage run(
            @HttpTrigger(
                name = "req", 
                methods = HttpMethod.GET, 
                authLevel = AuthorizationLevel.ANONYMOUS) 
            HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) 
        context.getLogger().info("Java HTTP trigger processed a request.");

        String secret = System.getenv("KEY_VAULT_URL");
        SecretClient secretClient = new SecretClientBuilder()
        .vaultUrl(secret)
        .credential(new DefaultAzureCredentialBuilder().build())
        .buildClient();
        
        KeyVaultSecret retrievedSecret = secretClient.getSecret("clientsecret");
        
        String clientSecretValue = retrievedSecret.getValue();
        byte[] clientSecretValueBytes = null;
        
        try 
            clientSecretValueBytes = clientSecretValue.getBytes("UTF-8");
         catch (UnsupportedEncodingException use) 
            clientSecretValueBytes = clientSecretValue.getBytes();   
        

        InputStream clientSecretValueStream = new ByteArrayInputStream(clientSecretValueBytes);

        GoogleCredentials credentials =  GoogleCredentials.fromStream(clientSecretValueStream)
            .createScoped("https://www.googleapis.com/auth/analytics.readonly") ;
        credentials.refreshIfExpired();
        AccessToken accessToken = credentials.getAccessToken();
 
        return request.createResponseBuilder(HttpStatusOK)
          .body("Access Token: " + accessToken.getTokenValue())
          .build();
    

【讨论】:

非常感谢!!!这就像一个冠军!请接受我的 50 点赏金作为小奖励,让我摆脱困境。 :) 欢迎您@LeeWhieldon!我很高兴听到它正常工作。【参考方案2】:

尝试使用 HttpRequestInitializer。这是我在 Java 中使用 Google Drive API 的示例代码。

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.services.drive.Drive;
import com.google.auth.http.HttpCredentialsAdapter;

// file 1 is the JSON credential file
// GoogleCredential have been deprecated so instead I use HttpRequestInitializer 
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(ServiceAccountCredentials.fromStream(new FileInputStream(file1))
        .createScoped(DriveScopes.all()));
Drive drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName(ApplicationName).build();

这是来自 Google doc 指令的代码:

HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = GoogleCredential
        .fromStream(new FileInputStream(KEY_FILE_LOCATION))
        .createScoped(DriveScopes.all());

// Construct the drive service object.
return new Drive.Builder(httpTransport, JSON_FACTORY, credential)
        .setApplicationName(APPLICATION_NAME).build();

【讨论】:

谢谢!这很有帮助!我只想返回访问令牌而不连接到 Google Drive API。我看到您将凭据直接传递到驱动器构建器中。返回访问令牌的方法是什么? @LeeWhieldon 据我所知,HttpRequestInitializer 可以直接用于身份验证(您可以看到,在我的情况下,我将服务帐户密钥作为参数传递)并且您无法从中获取访问令牌。也许您想要的是直接使用 HttpRequestInitializer 进行请求。您能否提供更多有关您如何使用访问令牌的背景信息? 当然,我想将一个临时的 Google Analytics 访问令牌传递到一个利用 azure 数据工厂的 api 调用中。因此,我需要返回访问令牌以传递到 azure 数据工厂管道,以使用 azure 函数来证实提取以返回访问令牌。 另外,您代码中的 GoogleCredential 已被贬值:cloud.google.com/java/docs/reference/google-api-client/latest/… 让我澄清一下,我需要 Java Web 令牌 (JWT),而不是用户私钥。希望这有助于澄清......

以上是关于类 Google.Apis.Auth.OAuth2.GoogleCredential.UnderlyingCredential.GetAccessTokenForRequestAsync() 在 Ja的主要内容,如果未能解决你的问题,请参考以下文章

30根据官方教程详解嵌套类内部类静态嵌套类局部类匿名类 ...

Java 静态成员类 非静态的成员类 局部类 匿名类

JavaSE基础(十 三 )---<内部类>成员内部类,静态内部类,局部内部类,匿名内部类,内部类的意义

Kotlin基础(十三) 嵌套类内部类和匿名内部类

java 内部类和外部类的关系

19-Java-核心类库2-包装类Integer类String类StringBuffer类StringBuilder类