在应用处理程序中,您可以通过读取 X-Appengine-Inbound-Appid 标头并将其与允许发出请求的 ID 列表进行比对来检查传入 ID。
向 Google API 声明身份
Google API 使用 OAuth 2.0 协议进行身份验证和授权。App Identity API 可以创建 OAuth 令牌,这些令牌可用于声明请求的来源是应用本身。getAccessToken() 方法会返回一个范围或范围列表的访问令牌。然后,可以在调用的 HTTP 标头中设置此令牌,以识别调用应用。
以下示例说明了如何使用 App Identity API 对 Google URL Shortener API 进行 REST 调用。
/** * Returns a shortened URL by calling the Google URL Shortener API. * * <p>Note: Error handling elided for simplicity. */publicStringcreateShortUrl(StringlongUrl)throwsException{ArrayList<String>scopes=newArrayList<>();scopes.add("https://www.googleapis.com/auth/urlshortener");finalAppIdentityServiceappIdentity=AppIdentityServiceFactory.getAppIdentityService();finalAppIdentityService.GetAccessTokenResultaccessToken=appIdentity.getAccessToken(scopes);// The token asserts the identity reported by appIdentity.getServiceAccountName()JSONObjectrequest=newJSONObject();request.put("longUrl",longUrl);URLurl=newURL("https://www.googleapis.com/urlshortener/v1/url?pp=1");HttpURLConnectionconnection=(HttpURLConnection)url.openConnection();connection.setDoOutput(true);connection.setRequestMethod("POST");connection.addRequestProperty("Content-Type","application/json");connection.addRequestProperty("Authorization","Bearer "+accessToken.getAccessToken());OutputStreamWriterwriter=newOutputStreamWriter(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.JSONTokenerresponseTokens=newJSONTokener(connection.getInputStream());JSONObjectresponse=newJSONObject(responseTokens);return(String)response.get("id");}else{try(InputStreams=connection.getErrorStream();InputStreamReaderr=newInputStreamReader(s,StandardCharsets.UTF_8)){thrownewRuntimeException(String.format("got error (%d) response %s from %s",connection.getResponseCode(),CharStreams.toString(r),connection.toString()));}}}
getAccessToken() 生成的令牌仅适用于 Google 服务。但是,您可以使用基础签名技术向其他服务声明应用的身份。signForApp() 方法将使用应用特有的私钥为字节签名,并且 getPublicCertificatesForApp() 方法将返回可用于验证签名的证书。
以下示例说明如何给 blob 签名并验证其签名:
// Note that the algorithm used by AppIdentity.signForApp() and// getPublicCertificatesForApp() is "SHA256withRSA"privatebyte[]signBlob(byte[]blob){AppIdentityService.SigningResultresult=appIdentity.signForApp(blob);returnresult.getSignature();}privatebyte[]getPublicCertificate()throwsUnsupportedEncodingException{Collection<PublicCertificate>certs=appIdentity.getPublicCertificatesForApp();PublicCertificatepublicCert=certs.iterator().next();returnpublicCert.getX509CertificateInPemFormat().getBytes("UTF-8");}privateCertificateparsePublicCertificate(byte[]publicCert)throwsCertificateException,NoSuchAlgorithmException{InputStreamstream=newByteArrayInputStream(publicCert);CertificateFactorycf=CertificateFactory.getInstance("X.509");returncf.generateCertificate(stream);}privatebooleanverifySignature(byte[]blob,byte[]blobSignature,PublicKeypk)throwsNoSuchAlgorithmException,InvalidKeyException,SignatureException{Signaturesignature=Signature.getInstance("SHA256withRSA");signature.initVerify(pk);signature.update(blob);returnsignature.verify(blobSignature);}privateStringsimulateIdentityAssertion()throwsCertificateException,UnsupportedEncodingException,NoSuchAlgorithmException,InvalidKeyException,SignatureException{// Simulate the sending app.Stringmessage="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.Certificatecert=parsePublicCertificate(publicCert);PublicKeypk=cert.getPublicKey();booleanisValid=verifySignature(blob,blobSignature,pk);returnString.format("isValid=%b for message: %s\n\tsignature: %s\n\tpublic cert: %s",isValid,message,Arrays.toString(blobSignature),Arrays.toString(publicCert));}
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["很难理解","hardToUnderstand","thumb-down"],["信息或示例代码不正确","incorrectInformationOrSampleCode","thumb-down"],["没有我需要的信息/示例","missingTheInformationSamplesINeed","thumb-down"],["翻译问题","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-08-20。"],[[["\u003cp\u003eThe \u003ccode\u003eREGION_ID\u003c/code\u003e is a Google-assigned code based on the region selected during app creation, included in App Engine URLs for apps created after February 2020, but it does not directly correspond to specific countries or provinces.\u003c/p\u003e\n"],["\u003cp\u003eThe App Identity API allows applications to find their application ID (project ID) to verify their identity to other App Engine apps, Google APIs, and third-party services, and it can be found using the \u003ccode\u003eApiProxy.getCurrentEnvironment().getAppId()\u003c/code\u003e method.\u003c/p\u003e\n"],["\u003cp\u003eApp Engine apps use URLs with the format \u003ccode\u003ehttps://PROJECT_ID.REGION_ID.r.appspot.com\u003c/code\u003e, and the \u003ccode\u003ecom.google.appengine.runtime.default_version_hostname\u003c/code\u003e attribute can retrieve the full hostname.\u003c/p\u003e\n"],["\u003cp\u003eTo verify the identity of an incoming request from another App Engine app, check the \u003ccode\u003eX-Appengine-Inbound-Appid\u003c/code\u003e header, which is added by the URLFetch service, but is only present on requests to the app's \u003ccode\u003eappspot.com\u003c/code\u003e domain.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003egetAccessToken()\u003c/code\u003e method can provide OAuth 2.0 tokens for authenticating with Google APIs, while the \u003ccode\u003esignForApp()\u003c/code\u003e and \u003ccode\u003egetPublicCertificatesForApp()\u003c/code\u003e methods facilitate identity assertion to third-party services using signing and certificate validation.\u003c/p\u003e\n"]]],[],null,[]]