我在 Google App Engine 上有两个应用程序,它们都在同一个帐户下运行,一个调用另一个通过 HTTPS 提供的服务。确保只允许第一个应用程序调用第二个应用程序的推荐方法是什么?
或者,有没有办法指定给定端点只能由在同一 GAE 帐户下运行的应用程序调用?
我在 Google App Engine 上有两个应用程序,它们都在同一个帐户下运行,一个调用另一个通过 HTTPS 提供的服务。确保只允许第一个应用程序调用第二个应用程序的推荐方法是什么?
或者,有没有办法指定给定端点只能由在同一 GAE 帐户下运行的应用程序调用?
让您的应用程序检查“X-Appengine-Inbound-Appid”标头并确保应用程序 ID 正确。仅当请求是由另一个 Google App Engine 应用发出且用户无法修改时,此标头才存在。
如果您使用的是 Python,则可以执行以下操作:
import webapp2
AUTHORIZED_APPS = ('my-first-app', 'my-other-app')
class MyHandler(webapp2.RequestHandler):
def dispatch(self):
app_id = self.request.headers.get('X-Appengine-Inbound-Appid', None)
if app_id in AUTHORIZED_APPS:
super(MyHandler, self).dispatch()
else:
self.abort(403)
对于标头中没有 X-Appengine-Inbound-Appid 的任何请求,这将引发 403。
此外,当使用 urlfetch 从一个应用程序向另一个应用程序发出请求时,请确保设置follow_redirects=False或不添加标头。
正如其他人指出的那样,依靠填写 X-Appengine-Inbound-Appid 标头是最简单的解决方案。我最近遇到了类似的问题,但我无法使用 X-Appengine-Inbound-Appid,因为 URLFetch 不可用(GAE Node.js)。以下是如何使用通过 OAuth 进行身份验证的服务帐户来解决问题。
在发件人方面,您需要设置一个服务帐户: https ://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount
然后在该应用程序中,您将需要获取服务帐户凭据: https ://developers.google.com/identity/protocols/application-default-credentials
然后,您可以使用凭据创建一个 authClient,您可以使用它来发送请求。您需要将 OAuth 范围添加到您的 authClient。最合乎逻辑的使用是https://www.googleapis.com/auth/userinfo.email
. 这将使接收者能够获取发件人服务帐户的电子邮件地址。https://developers.google.com/identity/protocols/googlescopes
以下是使其在(发件人)Node.js 中工作的代码:
process.env.GOOGLE_APPLICATION_CREDENTIALS = <PATH TO CREDENTIALS FILE>
google.auth.getApplicationDefault((err, authClient) => {
if (err) {
console.log("Failed to get default credentials: ", String(err));
return;
}
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped([
'https://www.googleapis.com/auth/userinfo.email'
]);
}
auth_client.request({
url: <RECEIVER URL>,
method: "GET"
}, (error, result, response) => {
// Process response
});
});
然后在接收方,您需要验证电子邮件地址是否与发件人服务帐户的电子邮件地址匹配。当应用程序引擎在本地调用时,OAuth 请求未正确验证,因此如果您想在本地进行测试,则必须自己进行 url 获取来验证请求。
接收器 Python:
scope = "https://www.googleapis.com/auth/userinfo.email"
allowed_users = set([
"<SENDER SERVICE ACCOUNT EMAIL>"
])
IS_DEV = os.environ["SERVER_SOFTWARE"][:3] == "Dev"
class MyHandler(webapp2.RequestHandler):
def get(self, clientId):
user = self.get_current_user()
if user in allowed_users:
# Do whatever you wanted
def get_current_user(self):
if IS_DEV:
token = self.request.headers.get("Authorization")[len("Bearer "):]
response = urlfetch.fetch(
"https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=%s" % token
)
return json.loads(response.content)["email"]
else:
return oauth.get_current_user(scope)
您可能希望查看 App Engine 的应用程序身份服务。
最简单的方法(在这种情况下也足够好)是在 HTTP 标头中包含一个秘密并在服务端检查它。
不知道这是否可行,但您可以尝试在 app.yaml 中将“登录:管理员”添加到您的 url 处理程序。
它适用于 cron/任务队列作业
https://developers.google.com/appengine/docs/python/config/cron#Securing_URLs_for_Cron