首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >谷歌云平台-云功能API - 401未经授权

谷歌云平台-云功能API - 401未经授权
EN

Stack Overflow用户
提问于 2020-07-12 15:42:24
回答 1查看 2.6K关注 0票数 1

我很难使用Java通过REST调用GCP云函数。

我执行的步骤是:

在我的代码中,为新创建的服务帐户Invoker"

  • download
  • 创建一个角色"Cloud
  • “的服务帐户,使用以下方法获得访问令牌:

代码语言:javascript
复制
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调用

代码语言:javascript
复制
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文档并没有真正的帮助。我想我已经搜遍了所有可能的地方。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-12 20:05:55

首先,同意,还不清楚.

然后,您必须知道(现在还不清楚),您需要一个访问令牌来调用,但是需要身份令牌来调用IAP (例如App )或私有云函数和云运行。这个身份标记需要谷歌签名。

而且,正如代码中提到的,您需要在计算机上有一个服务帐户,但是我建议您在GCP上避免这种情况,如果您使用默认身份验证(请参阅我的代码,在您的计算机上设置指向服务帐户密钥文件的GOOGLE_APPLICATION_CREDENTIALS env )。最好的方法是也不要在计算机上使用服务帐户密钥文件,但它还不可能(这是一个安全问题,海事组织,我正在与谷歌讨论这个.)

无论如何,这里有一个在Java中工作的代码片段(文档中没有.)

代码语言:javascript
复制
  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对象并手动设置令牌,您可以这样生成它

代码语言:javascript
复制
  String token = ((IdTokenProvider) credentials).idTokenWithAudience(myUri, Collections.EMPTY_LIST).getTokenValue();
  System.out.println(token);
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62863140

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档