Android客户端中来自AccountManager的AuthToken不再起作用。

37
我很沮丧。我正在尝试使用Google App Engine和Java作为服务器,在Android上构建回合制多人在线游戏。
它们似乎是完美的搭配。Android需要一个Google账户,而GAE使用Google账户进行身份验证,同时又是免费且可扩展的。
因此,在假期之前,我能够使用Android 2.0中的新AccountManager API从我的Android客户端对我的GAE应用进行身份验证。以下代码允许您访问用户的Google账户的AuthToken,然后将其用于身份验证,以便用户不必手动输入他们的账户用户名和密码:
   AccountManager mgr = AccountManager.get(this); 
   Account[] accts = mgr.getAccountsByType("com.google"); 
   Account acct = accts[0];
   AccountManagerFuture<Bundle> accountManagerFuture = mgr.getAuthToken(acct, "ah", null, this, null, null);
   Bundle authTokenBundle = accountManagerFuture.getResult(); 
   String authToken = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();

我当时能够将生成的AuthToken字符串附加到适当的URL上,并获得有效的cookie,然后可以将其用于所有进一步的请求。唯一的问题是,上周某个时候它突然停止工作了。现在当我尝试使用上述代码中的AuthToken时,我没有收到cookie,并且我的代码因缺少cookie而抛出NullPointerException。
当我回到旧的方式,即用户手动输入他们的Google用户名和密码并从 "https://www.google.com/accounts/ClientLogin" 获取AuthToken时,它就可以正常工作。
请告诉我有人已经构建了一个Android客户端,用于使用用户手机上的Google帐户的AuthToken访问Google应用引擎应用程序,并给我一些线索为什么这不再起作用。
我真的很想让这个工作。我的替代方案是要求用户输入他们的凭据(这很笨拙,他们不应该这样做),或者选择另一个服务器解决方案。
提前致谢。

我们可以在运行Google APIs的模拟器上测试这个吗? - Gopinath
1
对于那些想知道“适当的URL”是什么,以及如何“获取有效的cookie”的人,可以在这篇博客文章中得到清晰的解释,该文章还介绍了如何使authToken失效。 - thomas88wp
2个回答

26

我向一位Google工程师寻求帮助,发现我的authToken已经过期了。我最初在12月初(确切地说是12月9日)实现了该功能。AccountManager的作用是缓存authToken,因此自从12月9日以来,我一直在使用同一个authToken。当我度假回来时,它就过期了。

为了解决这个问题,我现在调用getAuthToken,然后调用该令牌上的invalidateAuthToken,并再次调用getAuthToken。这将生成有效的authToken,并且即使它有点笨拙,如果AccountManager每次都获得一个新的authToken或进行检查以查看缓存的authToken是否过期,则是不必要的,它也可以正常工作。

请注意,您不能混淆令牌类型和帐户类型:invalidateAuthToken必须使用“com.google”而不是“ah”进行调用,否则它将悄悄失败。


1
我曾经遇到过同样的问题,而invalidateAuthToken是关键。你需要被授予android.permission.MANAGE_ACCOUNTS权限。 - Billy Bob Bain
5
提示:当您调用invalidateAuthToken时,请确保传递帐户类型(“com.google”),而不是令牌类型(“health”)。我曾经犯过这个错误,由于invalidateAuthToken没有返回任何错误信息,因此追踪问题花费了一些时间。 - Artem
2
请不要误解,但请查看手册 http://developer.android.com/reference/android/accounts/AccountManager.html#get(android.content.Context)。 - kellogs
1
@Artem,你真是救了我一命。我试着在使令牌无效的过程中加入令牌类型,但它根本就不起作用。谢谢你!非常感谢! - Soham
2
@KK_07k11A0585 没有任何可能性是安卓会泄露任何人的谷歌密码。 - Aaron Dufour
显示剩余2条评论

4

虽然不是一个确切的答案,但我必须在第4行将“ah”替换为“android”,以便在使用Android v2.2.1的Android Nexus One上获得正确的令牌。对于其他设备/版本不确定。 然后第4行变成:

... = mgr.getAuthToken(acct, "ah", null, this, null, null);

into :

... = mgr.getAuthToken(acct, "android", null, this, null, null);

我遇到了和这个人一样的问题http://groups.google.com/group/android-developers/browse_thread/thread/d66ff537b04ec9a8,你的回复救了我。非常感谢! - atraudes
这里还有一个对他的问题的回复,供后代参考:http://groups.google.com/group/android-developers/browse_thread/thread/81d427905c5a54bb - atraudes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接