[英]How do I restrict Google App Engine Endpoints API access to only my Android applications?
我是一名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,但目前尚不清楚。
(将我的“应用” 验证到Google云端点而不是“用户”)将我的“应用”验证为Google Cloud Endpoints而不是“用户”
(如何保护使用Google Cloud Endpoints构建的API?) 如何保护使用Google Cloud Endpoints构建的API?
(限制访问谷歌云端点到Android应用) 限制访问谷歌云端点到Android应用程序
我有类似的问题,不是在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]
hash=[ example.com/api/do_thing?param1=foo&hash=[some long hex value]
。
然后,在服务器端,我首先从url请求中删除哈希,然后对剩余的所有内容运行哈希。 最后,检查计算的散列是否与随请求一起发送的散列匹配,如果不匹配,则可以拒绝该请求。
但是,您的密钥仍然保密,这一点非常重要。 您必须在Android上小心这一点,因为有人可能会尝试反编译您的APK。
面对同样的问题比你! 在没有Google用户帐户的情况下验证Android端点是不可能的!
所以这是我解决这个问题的方法,没有任何用户交互(也许不是正确但有效,你有强大的身份验证(SHA1 + Google帐户)):
这是我的安卓代码
获取并构建有效凭据
//Get all accounts from my Android Phone
String validGoogleAccount = null;
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
//Just store mail if countain gmail.com
if (account.name.toString().contains("gmail.com")&&account.type.toString().contains("com.google")){
validGoogleAccount=account.name.toString();
}
}
}
//Build Credential with valid google account
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this,"server:client_id:301991144702-5qkqclsogd0b4fnkhrja7hppshrvp4kh.apps.googleusercontent.com");
credential.setSelectedAccountName(validGoogleAccount);
使用此凭据进行安全呼叫
Campagneendpoint.Builder endpointBuilder = new Campagneendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), credential);
这是我的API后缀代码: API注释
@Api(
scopes=CONSTANTES.EMAIL_SCOPE,
clientIds = {CONSTANTES.ANDROID_CLIENT_ID,
CONSTANTES.WEB_CLIENT_ID,
com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {CONSTANTES.ANDROID_AUDIENCE},
name = "campagneendpoint",
version = "v1"
)
方法代码:
public Collection<Campagne> getCampagnes(@Named("NumPortable")String NumPortable, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
return CampagneCRUD.getInstance().findCampagne(NumPortable);
}
目前,它只适用于Android(我不知道我们将如何做IOS ..)..
希望它会对你有所帮助!
Google提供了针对Android
, web
和iOS
执行此操作的方法。步骤包括:
这些步骤在Google的Using Auth with Endpoints和此博客上都有详细的详细说明
面对同样的问题,这是我研究的结果:
但是:
如果我没有向方法添加用户参数:检查有关Android应用程序客户端ID不起作用
如果我添加USER参数但不要求用户选择其谷歌帐户来创建凭证...也不起作用...
结论:似乎必须连接用户帐户以检查要执行的应用程序客户端ID ...我真的不明白为什么因为2个进程之间不存在链接
选择您的项目,转到凭证部分
创建一个新的api密钥
创建一个新的Android密钥
单击“编辑允许的Android应用程序”并输入您的SHA1密钥; 你的android包名
如果这解决了问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.