gpt4 book ai didi

java - 如何为 Cloud Function HTTP 触发器生成 JWT?

转载 作者:行者123 更新时间:2023-12-01 17:36:06 32 4
gpt4 key购买 nike

我想要做的是生成一个 JWT,用于在我部署的 GCP 云函数上调用 HTTP 触发器。我已经使用“allUsers”部署了我的函数并验证了它的工作原理,但我希望它更安全,因此我需要将 JWT 附加到我的 HTTP 请求。我正在关注this code以下片段大部分来自于此。我想我已经很接近了,但还没有完全实现。在下面的所有示例等中,我已将项目名称更改为 PROJECT_NAME。

首先,我创建了一个名为 testharness-sa 的服务帐户并下载了其 key 文件。当我运行测试时,我有一个环境变量 GOOGLE_APPLICATION_CREDENTIALS 指向该文件。然后我运行了以下命令:

gcloud functions add-iam-policy-binding gopubsub \
--member='serviceAccount:testharness-sa@PROJECT_NAME.iam.gserviceaccount.com' \
--role='roles/cloudfunctions.invoker'

这通过列出我的云函数上的所有当前绑定(bind)(包括 testharness-sa)给了我确认。

我的代码的核心是这样的:

    private String getSignedJwt() {
GoogleCredentials credentials = GoogleCredentials
.getApplicationDefault()
.createScoped(Collections.singleton(IAM_SCOPE));
long now = System.currentTimeMillis();
RSAPrivateKey privateKey = (RSAPrivateKey) credentials.getPrivateKey();
Algorithm algorithm = Algorithm.RSA256(null, privateKey);
return JWT.create()
.withKeyId(credentials.getPrivateKeyId())
.withIssuer(credentials.getClientEmail())
.withSubject(credentials.getClientEmail())
.withAudience(OAUTH_TOKEN_AUDIENCE)
.withIssuedAt(new Date(now))
.withExpiresAt(new Date(now + EXPIRATION_TIME_IN_MILLIS))
.withClaim("target_audience", clientId)
.sign(algorithm);
}

这给了我一个签名的 JWT。据我了解,这用于调用 GCP 来获取最终的 JWT,我可以用它来调用我的云函数。

生成签名的 JWT 后,我会像这样使用它:

        String jwt = getSignedJwt();
final GenericData tokenRequest = new GenericData()
.set("grant_type", JWT_BEARER_TOKEN_GRANT_TYPE)
.set("assertion", jwt);
final UrlEncodedContent content = new UrlEncodedContent(tokenRequest);

final HttpRequestFactory requestFactory = httpTransport.createRequestFactory();

final HttpRequest request = requestFactory
.buildPostRequest(new GenericUrl(OAUTH_TOKEN_URI), content)
.setParser(new JsonObjectParser(JacksonFactory.getDefaultInstance()));

HttpResponse response = request.execute();
...

因此它获取签名的 JWT 并发出请求以获取最终的 JWT,然后...失败。错误是“无效的 JWT:受众检查失败”看起来我的参数不好,所以让我们看看我的参数(它们实际上是常量,而不是参数):

    private static final String IAM_SCOPE = "https://www.googleapis.com/auth/iam";
//"https://www.googleapis.com/auth/cloud-platform";
private static final String OAUTH_TOKEN_URI = "https://oauth2.googleapis.com/token";
//"https://www.googleapis.com/oauth2/v4/token";
private static final String OAUTH_TOKEN_AUDIENCE = "https://us-central1-PROJECT_NAME.cloudfunctions.net/gopubsub";
//"https://www.googleapis.com/token";
private static final String JWT_BEARER_TOKEN_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
private static final long EXPIRATION_TIME_IN_MILLIS = 3600 * 1000L;

我添加了其他变体作为针对常量的注释。

根据错误消息,我使用的受众群体值似乎是错误的。 This page建议受众应该是服务帐户电子邮件,我想我在其他地方看到它应该是云功能的 URL,但这些都不适合我。

我知道这可以工作,因为我可以发出这个命令:

gcloud auth print-identity-token

这给了我最终的 JWT(只要我有 GOOGLE_APPLICATION_CREDENTIALS 指向我的 json 文件)。我可以将该 JWT 粘贴到curl 命令中并成功调用 HTTP 触发器,如果​​我将 JWT 排除在外,则会失败,因此我知道 JWT 正在被检查。但到目前为止,我不知道如何从我的 Java 代码中执行与 gcloud auth print-identity-token 等效的操作。有人知道吗?

最佳答案

尽管有错误消息,但我发现答案与范围无关。它实际上与我传递的 clientId 值相关(虽然在代码中存在,但我的问题中并未真正提及)。我使用的是在服务帐户 json 文件中找到的值,这是一串非常长的数字。这就是问题所在。它必须是我的 HTTP 触发器的 URL。所以这些是我最终得到的常量:

    private static final String IAM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
private static final String OAUTH_TOKEN_URI = "https://www.googleapis.com/oauth2/v4/token";
private static final String OAUTH_TOKEN_AUDIENCE = "https://www.googleapis.com/oauth2/v4/token";
private static final String JWT_BEARER_TOKEN_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
private static final long EXPIRATION_TIME_IN_MILLIS = 3600 * 1000L;

事实上,如果我删除对 IAM_SCOPE 的所有引用,它仍然有效,所以我认为这并不重要。将其组合在一起的代码现在如下所示:

        return JWT.create()
.withKeyId(credentials.getPrivateKeyId())
.withIssuer(credentials.getClientEmail())
.withSubject(credentials.getClientEmail())
.withAudience(OAUTH_TOKEN_AUDIENCE)
.withIssuedAt(new Date(now))
.withExpiresAt(new Date(now + EXPIRATION_TIME_IN_MILLIS))
.withClaim("target_audience", targetURL)
.sign(algorithm);

具体的更改是 withClaim() 调用,它现在包含我要调用的 URL。完成此操作后,代码将返回我想要的 JWT,事实上,当我调用安全的 HTTP 触发器 URL 时,它确实可以工作。希望对其他人有帮助。

关于java - 如何为 Cloud Function HTTP 触发器生成 JWT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61037206/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com