我在Google App Engine上有两个应用程序,两个都在同一个帐户下运行,另一个通过HTTPS调用另一个应用程序提供的服务。确保只允许第一个应用程序调用第二个应用程序的推荐方法是什么?
或者,有没有办法指定给定的端点只能由在同一GAE帐户下运行的应用程序调用?
答案 0 :(得分:3)
让您的应用程序检查“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 ,否则标题不会被添加。
答案 1 :(得分:3)
正如其他人所指出的那样,依靠标题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,您可以使用它来发送请求。您需要向authClient添加OAuth范围。最常用的逻辑是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请求未经过正确的身份验证,因此如果您想在本地进行测试,则必须自己进行网址获取以验证请求。
Receiver 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)
答案 2 :(得分:2)
您可能希望查看App Engine的Application Identity服务。
答案 3 :(得分:1)
最简单的方法(在这种情况下足够好)将在HTTP标头中包含一个秘密,并在服务端进行检查。
答案 4 :(得分:0)
Dunno如果这样可行,但您可以尝试将“login:admin”添加到app.yaml中的url处理程序。
适用于cron /任务队列作业
https://developers.google.com/appengine/docs/python/config/cron#Securing_URLs_for_Cron