在应用处理程序中,您可以通过读取 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-03-07。"],[[["The `REGION_ID` 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."],["The 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 `ApiProxy.getCurrentEnvironment().getAppId()` method."],["App Engine apps use URLs with the format `https://PROJECT_ID.REGION_ID.r.appspot.com`, and the `com.google.appengine.runtime.default_version_hostname` attribute can retrieve the full hostname."],["To verify the identity of an incoming request from another App Engine app, check the `X-Appengine-Inbound-Appid` header, which is added by the URLFetch service, but is only present on requests to the app's `appspot.com` domain."],["The `getAccessToken()` method can provide OAuth 2.0 tokens for authenticating with Google APIs, while the `signForApp()` and `getPublicCertificatesForApp()` methods facilitate identity assertion to third-party services using signing and certificate validation."]]],[]]