我是一名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和audiences)中 除了“添加用户参数” - 因为我不需要用户身份验证。
然后我部署了App引擎,我仍然可以通过API资源管理器(https://your_app_id.appspot.com/_ah/api/explorer)访问API (我没有添加API_EXPLORER客户端ID)
我使用在使用端点库构建的APK进行测试后再添加客户端ID,并且仍然可以访问API。
是否必须向所有端点API添加“用户参数”?实现我的目的(将API限制为仅限我的Android应用程序)。
我可以从Android客户端传递null作为userAccount名称并忽略服务器上的用户参数值(因为它将为null)?这是否确保API只能从我的Android应用程序访问(因为我的包名称和APK的SHA1生成了客户端ID?)
我是否应该为此目的使用类似服务帐户的东西?
文档说,对于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构建器(如其他一些帖子所示) 致命的致命异常。所以,我们不能传递空账号。
我可以在没有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云终端验证我的“应用”而不是“用户”) Authenticate my "app" to Google Cloud Endpoints not a "user"
(如何保护使用Google Cloud Endpoints构建的API?) How do I protect my API that was built using Google Cloud Endpoints?
(限制访问Google云端点到Android应用) Restrict access to google cloud endpoints to Android app
答案 0 :(得分:8)
我有类似的问题,不是在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。
答案 1 :(得分:3)
面对同样的问题!不使用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 ..)..
希望它会对你有帮助!
答案 2 :(得分:3)
Google为Android
,web
和iOS
提供了执行此操作的方法
步骤包括:
这些步骤在Google Using Auth with Endpoints以及此blog
上详细列出。答案 3 :(得分:1)
面对同样的问题,这是我研究的结果:
但是:
如果我不向方法添加用户参数:检查Android应用程序客户端ID不起作用
如果我添加USER参数但不要求用户选择其Google帐户来创建凭据...也不起作用...
结论:似乎必须连接用户帐户以检查要执行的应用程序客户端ID ...我真的不明白为什么因为2个进程之间不存在链接
答案 4 :(得分:0)
选择您的项目,转到凭证部分
创建一个新的api密钥
创建一个新的Android密钥
点击&#34;编辑允许的Android应用程序&#34;并输入您的SHA1密钥;你的android包名称
如果这解决了问题,请告诉我。