我正在构建一个Web服务,并希望使用用户的Google账户凭证。
该服务运行在GAE上,将拥有一个Web客户端和一个Android原生客户端。
这是我第一次尝试这样的事情,我一直在阅读关于OpenID和Android AccountManager库的内容。
我仍然不确定在我的Datastore中存储用户的选项是什么?我应该使用什么标识符?是否可能在本机Android应用程序上使用OpenID?
任何帮助和/或指针都将不胜感激。谢谢。
我正在构建一个Web服务,并希望使用用户的Google账户凭证。
该服务运行在GAE上,将拥有一个Web客户端和一个Android原生客户端。
这是我第一次尝试这样的事情,我一直在阅读关于OpenID和Android AccountManager库的内容。
我仍然不确定在我的Datastore中存储用户的选项是什么?我应该使用什么标识符?是否可能在本机Android应用程序上使用OpenID?
任何帮助和/或指针都将不胜感激。谢谢。
我们在上一个项目中也有类似的需求:GAE后端与GWT前端以及Android / iPhone客户端。此外,我们不希望存储用户凭据。
因此,我们选择使用OpenID,这是一种不幸的Web标准,与移动设备不兼容,但可行。
在GAE端,我们只需启用联合登录即可获得OpenID。
在移动设备上,当用户需要登录时,我们向他们呈现一个OpenID认证器列表(Google、Yahoo等),然后我们打开一个本地浏览器(非嵌入式浏览器),并将用户引导到所选的OpenID身份验证网站。好处是用户的浏览器通常已经记住了用户名/密码,因此这一步只需要用户按下一个按钮即可。
这一切都很简单。现在是棘手的部分: 用户确认登录后,OpenID将重定向回我们的GAE返回URL(在发出请求时需要提供此URL)。在此URL上,我们创建一个自定义URL,例如:
yourappname://usrname#XXXYYYZZZ
其中 XXXYYYZZZZ 代表授权令牌。我们从返回页面获取此令牌,它存储为 ACSID cookie:我们使用一些 JSP 代码读取此 cookie 并将其包装到上面的自定义 URL 中。
然后我们注册我们的 Android 和 iPhone 应用程序来处理 yourappname://
URL,这样当用户单击此链接时,我们的应用程序会被调用并且链接被传递给它。我们从此链接中提取用户名和令牌,并在 REST 请求中使用它来访问 GAE 后端。
如果您有任何问题,我很乐意更新此帖子。
更新:
生产 AppEngine 上的用户会话 cookie 名称为 ACSID
,而开发 AppEngine 服务器上的名称为 dev_appserver_login
。
我花了大约一周的时间寻找一种适合且现代化的方法 - 不需要使用网络浏览器,而是使用Android账户管理器。
如果你想使用Google账户和AccountManager来识别用户,你可以:
通过后台线程通过AccountManager获取他在Google Contacts中的令牌(认证令牌类型为"cp"):
public String getUserToken(Activity activity)
{
AccountManager accountManager = AccountManager.get(activity);
AccountManagerFuture<Bundle> amf = accountManager.getAuthTokenByFeatures("com.google", "cp", null, activity, Bundle.EMPTY, Bundle.EMPTY, null, null );
Bundle bundle = null;
try {
bundle = amf.getResult();
String name = (String) bundle.get(AccountManager.KEY_ACCOUNT_NAME);
String type = (String) bundle.get(AccountManager.KEY_ACCOUNT_TYPE);
String token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
return token;
} catch (OperationCanceledException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (AuthenticatorException e) {
e.printStackTrace();
}
return null;
}
将收到的UserToken通过安全通道发送到服务器。
使用gdata库(Google Data API library)在服务器上通过google验证令牌:
public String getUserId(String token)
{
ContactsService contactsService = new ContactsService("Taxi");
contactsService.setUserToken(token);
IFeed feed = null;
try {
feed = contactsService.getFeed(new URL("https://www.google.com/m8/feeds/contacts/default/full?max-results=10000"), ContactFeed.class);
} catch (IOException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
if (feed == null)
return null;
String externalId = feed.getId();
IPerson person = feed.getAuthors().get(0);
String email = person.getEmail();
String name = person.getName();
String nameLang = person.getNameLang();
return externalId;
}
Google令牌可能会过期(通常在一小时后),因此如果您无法在服务器上验证令牌,则必须向客户端发送响应,使令牌失效并获取新的令牌。使用帐户管理器使令牌失效:
public void invalidateUserToken(Context context, String token)
{
AccountManager accountManager = AccountManager.get(context);
accountManager.invalidateAuthToken("com.google", token);
}