如何限制Google App Engine端点API只能访问我的Android应用程序?

Kak*_*udu 23 google-app-engine android google-cloud-endpoints

我是一名Android开发人员,为我的应用构建了我的第一个Google App Engine(java)后端.除了我的应用程序之外,我不希望任何其他人访问此API.(我计划在我的Android应用程序中使用App引擎验证InApp购买).我的数据与用户无关,因此我不希望用户即使使用他们的Google帐户(在网络或Android设备上)登录也能访问我的API.

我按照"在API后端中指定授权客户端"(https://developers.google.com/appengine/docs/java/endpoints/auth)中提到的步骤进行操作,例如生成客户端ID并将其添加到@Api(clientIds和观众)除了"添加用户参数" - 因为我不需要用户身份验证.

然后我部署了App引擎,我仍然可以通过API资源管理器访问API(https://your_app_id.appspot.com/_ah/api/explorer)(我还没有添加API_EXPLORER客户端ID)

我在添加客户端ID之前使用使用端点库构建的APK进行了测试,并且仍然可以访问API.

  • 是否必须向所有端点API添加"用户参数"?实现我的目的(限制API到我的Android应用程序).

  • 我可以从Android客户端传递null作为userAccount名称并忽略服务器上的用户参数值(因为它将为null)?这是否确保API只能从我的Android应用程序访问(因为客户端ID是为我的包名和APK的SHA1生成的?)

  • 我应该为此目的使用类似服务帐户的东西吗?

文档说,对于Android,必须添加Android和Web客户端ID,并且受众必须与Web客户端ID相同.这是否可以访问任何其他Web客户端?我可以跳过提及Web客户端ID并仍然达到我的目的吗?

感谢您的时间和帮助.

......随着我的进一步调查而更新......

我做了以下事情:

  • 在后端的API中添加了User参数 - 但没有检查空值.无需传递任何凭据即可访问API(来自Android调试APK和API资源管理器)

  • 然后,我试过了

    mCredential = GoogleAccountCredential.usingAudience(this,"server:client_id:"+ WEB_CLIENT_ID); mCredential.setSelectedAccountName(NULL);

并将此凭据传递给API构建器(如其他一些帖子中所建议的)导致致命异常.所以,我们不能传递null帐户名.

  • 我可以在没有OAuth的情况下使用API​​资源管理器调用API.但是当我启用OAuth时,它提示错误,说不允许此客户端ID!(我还没有在client_ids {}中添加com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID)

  • 然后我添加了代码,如果用户为null,则在后端抛出OAuthRequestException.这导致API资源管理器在没有OAuth的情况下收到错误.将API_EXPLORER_CLIENT_ID添加到client_ids后,它可以启用OAuth

  • 添加了从我的Android应用程序传递有效用户帐户名(电子邮件)的代码.然后,我只能使用我的发布APK访问API.即使是调试APK也会有异常! - 这是我的预期.所以,我认为没有其他Android应用程序能够访问此API.

因此,不检查后端API上的null用户是个坏主意(如其他帖子所示).它没有提到任何client_ids而没有User param.

我现在唯一的问题是:如果有人可以从APK中找出WEB_CLIENT_ID,他们是否可以使用它来构建一个Web客户端来访问我的API(我没有在代码中的任何地方提到过客户端秘密.所以我认为这是不可能的).


我确实搜索了Google群组和Stackoverflow,但目前尚不清楚.

spe*_*ane 9

我有类似的问题,不是在Android和App Engine之间,而是在单独的服务器和App Engine之间.我处理它的方法是将签名哈希字段作为参数添加到每个API调用.如果请求有不正确的签名,则会被拒绝.

例如,假设您的API端点是example.com/api/do_thing?param1=foo.我会将整个url和一个密钥一起哈希,然后将哈希的结果附加到请求中:example.com/api/do_thing?param1=foo&hash=[some long hex value].

然后,在服务器端,我首先从url请求中删除哈希,然后对剩余的所有内容运行哈希.最后,检查计算的散列是否与随请求一起发送的散列匹配,如果不匹配,则可以拒绝该请求.

但是,您的密钥仍然保密,这一点非常重要.您必须在Android上小心这一点,因为有人可能会尝试反编译您的APK.