App Identity API für gebündelte Legacy-Dienste

Regions-ID

REGION_ID ist ein abgekürzter Code, den Google anhand der Region zuweist, die Sie beim Erstellen Ihrer Anwendung ausgewählt haben. Der Code bezieht sich nicht auf ein Land oder eine Provinz, auch wenn einige Regions-IDs häufig verwendeten Länder- und Provinzcodes ähneln können. Bei Anwendungen, die nach Februar 2020 erstellt wurden, ist REGION_ID.r in den App Engine-URLs enthalten. Bei Anwendungen, die vor diesem Datum erstellt wurden, ist die Regions-ID in der URL optional.

Hier finden Sie weitere Informationen zu Regions-IDs.

Mit der App Identity API können Anwendungen ihre Anwendungs-ID (auch als Projekt-ID bezeichnet) ermitteln. Mithilfe der ID können App Engine-Anwendungen ihre Identität gegenüber anderen App Engine-Anwendungen, Google APIs sowie Anwendungen und Diensten von Drittanbietern bestätigen. Die Anwendungs-ID kann auch zum Generieren einer URL oder E-Mail-Adresse oder zum Ausführen einer Laufzeitentscheidung herangezogen werden.

Projekt-ID abrufen

Die Projekt-ID lässt sich mit der Methode ApiProxy.getCurrentEnvironment().getAppId() ermitteln.

Hostname der Anwendung abrufen

App Engine-Anwendungen werden standardmäßig über URLs im Format https://PROJECT_ID.REGION_ID.r.appspot.com bereitgestellt, wobei die Projekt-ID Teil des Hostnamens ist. Wenn eine Anwendung von einer benutzerdefinierten Domain bereitgestellt wird, muss möglicherweise die gesamte Komponente des Hostnamens abgerufen werden. Verwenden Sie dazu das Attribut com.google.appengine.runtime.default_version_hostname von CurrentEnvironment.

@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
  resp.setContentType("text/plain");
  ApiProxy.Environment env = ApiProxy.getCurrentEnvironment();
  resp.getWriter().print("default_version_hostname: ");
  resp.getWriter()
      .println(env.getAttributes().get("com.google.appengine.runtime.default_version_hostname"));
}

Identität gegenüber anderen App Engine-Anwendungen bestätigen

Zum Ermitteln der Identität der App Engine-Anwendung, die eine Anfrage an Ihre App Engine-Anwendung sendet, verwenden Sie den Anfrage-Header X-Appengine-Inbound-Appid. Dieser Header wird der Anfrage vom URLFetch-Dienst hinzugefügt und kann vom Nutzer nicht geändert werden. Daher wird die ID der Anwendung, die die Anfrage ausführt (falls vorhanden), sicher angezeigt.

Anforderungen:

  • Nur Aufrufe, die an die Domain appspot.com Ihrer Anwendung gesendet werden, enthalten den Header X-Appengine-Inbound-Appid. Aufrufe an benutzerdefinierte Domains enthalten den Header nicht.
  • Ihre Anfragen müssen so eingerichtet sein, dass sie keinen Weiterleitungen folgen. Wenn Sie die Klasse URLFetchService verwenden, muss Ihre Anwendung doNotFollowRedirect angeben. Anwendungen, die in der Java 8-Laufzeit ausgeführt werden, verwenden standardmäßig nicht den URL-Abrufdienst. In dieser Anleitung wird gezeigt, wie Sie den URL-Abrufdienst aktivieren können.
  • Wenn Ihre Anwendung java.net verwendet, ändern Sie Ihren Code dahingehend, dass Weiterleitungen nicht gefolgt wird:
    connection.setInstanceFollowRedirects(false);

Die eingehende ID können Sie in Ihrem Anwendungs-Handler prüfen. Vergleichen Sie dazu den Inhalt des Headers X-Appengine-Inbound-Appid mit der Liste der IDs, die Anfragen senden dürfen.

Identität gegenüber Google APIs bestätigen

Google APIs verwenden zur Authentifizierung und Autorisierung das OAuth 2.0-Protokoll. Die App Identity API kann OAuth-Tokens erstellen, mit denen bestätigt werden kann, dass die Quelle einer Anfrage die Anwendung selbst ist. Die Methode getAccessToken() gibt ein Zugriffstoken für einen Bereich oder für eine Liste von Bereichen zurück. Dieses Token kann dann in den HTTP-Headern eines Aufrufs festgelegt werden, um die aufrufende Anwendung zu identifizieren.

Das folgende Beispiel zeigt, wie mit der App Identity API ein REST-Aufruf an die Google URL Shortener API ausgeführt wird.

/**
 * Returns a shortened URL by calling the Google URL Shortener API.
 *
 * <p>Note: Error handling elided for simplicity.
 */
public String createShortUrl(String longUrl) throws Exception {
  ArrayList<String> scopes = new ArrayList<>();
  scopes.add("https://www.googleapis.com/auth/urlshortener");
  final AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
  final AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(scopes);
  // The token asserts the identity reported by appIdentity.getServiceAccountName()
  JSONObject request = new JSONObject();
  request.put("longUrl", longUrl);

  URL url = new URL("https://www.googleapis.com/urlshortener/v1/url?pp=1");
  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  connection.setDoOutput(true);
  connection.setRequestMethod("POST");
  connection.addRequestProperty("Content-Type", "application/json");
  connection.addRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());

  OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
  request.write(writer);
  writer.close();

  if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
    // Note: Should check the content-encoding.
    //       Any JSON parser can be used; this one is used for illustrative purposes.
    JSONTokener responseTokens = new JSONTokener(connection.getInputStream());
    JSONObject response = new JSONObject(responseTokens);
    return (String) response.get("id");
  } else {
    try (InputStream s = connection.getErrorStream();
        InputStreamReader r = new InputStreamReader(s, StandardCharsets.UTF_8)) {
      throw new RuntimeException(
          String.format(
              "got error (%d) response %s from %s",
              connection.getResponseCode(), CharStreams.toString(r), connection.toString()));
    }
  }
}

Der Dienstkontoname gibt die Identität der Anwendung wieder. Dieser lautet in der Regel applicationid@appspot.gserviceaccount.com. Sie können den genauen Wert mit der Methode getServiceAccountName() abrufen. Für Dienste, die ACLs anbieten, können Sie der Anwendung den Zugriff über dieses Konto gewähren.

Identität gegenüber Diensten von Drittanbietern bestätigen

Das von getAccessToken() generierte Token funktioniert nur in Verbindung mit Google-Diensten. Sie können jedoch die zugrunde liegende Signaturtechnologie verwenden, um die Identität Ihrer Anwendung gegenüber anderen Diensten zu bestätigen. Die Methode signForApp() signiert die Byte mit einem privaten Schlüssel speziell für Ihre Anwendung. Die Methode getPublicCertificatesForApp() gibt Zertifikate zurück, mit denen die Signatur validiert werden kann.

Hier ist ein Beispiel für das Signieren eines Blobs und die anschließende Überprüfung der Signatur:
// Note that the algorithm used by AppIdentity.signForApp() and
// getPublicCertificatesForApp() is "SHA256withRSA"

private byte[] signBlob(byte[] blob) {
  AppIdentityService.SigningResult result = appIdentity.signForApp(blob);
  return result.getSignature();
}

private byte[] getPublicCertificate() throws UnsupportedEncodingException {
  Collection<PublicCertificate> certs = appIdentity.getPublicCertificatesForApp();
  PublicCertificate publicCert = certs.iterator().next();
  return publicCert.getX509CertificateInPemFormat().getBytes("UTF-8");
}

private Certificate parsePublicCertificate(byte[] publicCert)
    throws CertificateException, NoSuchAlgorithmException {
  InputStream stream = new ByteArrayInputStream(publicCert);
  CertificateFactory cf = CertificateFactory.getInstance("X.509");
  return cf.generateCertificate(stream);
}

private boolean verifySignature(byte[] blob, byte[] blobSignature, PublicKey pk)
    throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
  Signature signature = Signature.getInstance("SHA256withRSA");
  signature.initVerify(pk);
  signature.update(blob);
  return signature.verify(blobSignature);
}

private String simulateIdentityAssertion()
    throws CertificateException, UnsupportedEncodingException, NoSuchAlgorithmException,
    InvalidKeyException, SignatureException {
  // Simulate the sending app.
  String message = "abcdefg " + Calendar.getInstance().getTime().toString();
  byte[] blob = message.getBytes();
  byte[] blobSignature = signBlob(blob);
  byte[] publicCert = getPublicCertificate();

  // Simulate the receiving app, which gets the certificate, blob, and signature.
  Certificate cert = parsePublicCertificate(publicCert);
  PublicKey pk = cert.getPublicKey();
  boolean isValid = verifySignature(blob, blobSignature, pk);

  return String.format(
      "isValid=%b for message: %s\n\tsignature: %s\n\tpublic cert: %s",
      isValid, message, Arrays.toString(blobSignature), Arrays.toString(publicCert));
}

Name des standardmäßigen Cloud Storage-Buckets abrufen

Alle Anwendungen können einen standardmäßigen Cloud Storage-Bucket haben, dem 5 GB kostenloser Speicher und ein kostenloses Kontingent für E/A-Vorgänge zugeordnet sind.

Sie können den Namen des Standard-Buckets mit der App Identity API abrufen. Rufen Sie hierzu AppIdentityService.getDefaultGcsBucketName auf.