我很难使用Java通过REST调用GCP云函数。
我执行的步骤是:
在我的代码中,为新创建的服务帐户Invoker"
private String getAuthToken() {
File credentialsPath = new File(PATH_TO_JSON_KEY_FILE);
GoogleCredentials credentials;
try (FileInputStream serviceAccountStream = new FileInputStream(credentialsPath)) {
credentials = ServiceAccountCredentials.fromStream(serviceAccountStream);
return credentials
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"))
.refreshAccessToken()
.getTokenValue();
} catch (IOException e) {
throw new RuntimeException("Action could not be performed");
}
}执行REST调用
public <Payload, Response> ResponseEntity<Response> callCloudFunction(
String endpoint,
Payload payload,
Class<Response> klazz
) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
String url = gCloudUrl + endpoint;
String token = getAuthToken();
String payloadString = null;
if (payload != null) {
try {
ObjectMapper objectMapper = new ObjectMapper();
payloadString = objectMapper.writeValueAsString(payload);
} catch (JsonProcessingException e) {
System.out.println(e.getMessage());
throw new RuntimeException("Could not perform action");
}
}
headers.add("Authorization", String.format("Bearer %s", token));
HttpEntity<String> entity = new HttpEntity<>(payloadString, headers);
return restTemplate.exchange(url, HttpMethod.POST, entity, klazz);
}该实现看起来很好,但作为回应,我得到401未经授权。
不幸的是,GCP文档并没有真正的帮助。我想我已经搜遍了所有可能的地方。
发布于 2020-07-12 20:05:55
首先,同意,还不清楚.
然后,您必须知道(现在还不清楚),您需要一个访问令牌来调用,但是需要身份令牌来调用IAP (例如App )或私有云函数和云运行。这个身份标记需要谷歌签名。
而且,正如代码中提到的,您需要在计算机上有一个服务帐户,但是我建议您在GCP上避免这种情况,如果您使用默认身份验证(请参阅我的代码,在您的计算机上设置指向服务帐户密钥文件的GOOGLE_APPLICATION_CREDENTIALS env )。最好的方法是也不要在计算机上使用服务帐户密钥文件,但它还不可能(这是一个安全问题,海事组织,我正在与谷歌讨论这个.)
无论如何,这里有一个在Java中工作的代码片段(文档中没有.)
String myUri = "https://path/to/url";
// You can use here your service account key file. But, on GCP you don't require a service account key file.
// However, on your computer, you require one because you need and identity token and you can generate it with your user account (long story... I'm still in discussion with Google about this point...)
Credentials credentials = GoogleCredentials.getApplicationDefault().createScoped("https://www.googleapis.com/auth/cloud-platform");
IdTokenCredentials idTokenCredentials = IdTokenCredentials.newBuilder()
.setIdTokenProvider((IdTokenProvider) credentials)
.setTargetAudience(myUri).build();
HttpRequestFactory factory = new NetHttpTransport().createRequestFactory(new HttpCredentialsAdapter(idTokenCredentials));
HttpRequest request = factory.buildGetRequest(new GenericUrl(myUri));
HttpResponse httpResponse = request.execute();
System.out.println(CharStreams.toString(new InputStreamReader(httpResponse.getContent(), Charsets.UTF_8)));注如果您想继续使用RestTemplate对象并手动设置令牌,您可以这样生成它
String token = ((IdTokenProvider) credentials).idTokenWithAudience(myUri, Collections.EMPTY_LIST).getTokenValue();
System.out.println(token);https://stackoverflow.com/questions/62863140
复制相似问题