Web服务凭证 - OpenID/Android AccountManager?

Tom*_*ler 30 openid android accountmanager google-cloud-datastore

我正在建立一个网络服务,并希望使用用户的谷歌帐户凭据.

该服务在GAE上运行,并将具有Web客户端和Android本机客户端.

这是我第一次尝试这样的东西,我一直在阅读有关OpenID和Android AccountManager库的内容.

我仍然不确定在我的数据存储区中存储用户有哪些选择.我应该使用什么标识符?是否可以在原生Android应用程序上使用OpenID?

任何帮助和/或指针将不胜感激.谢谢.

Pet*_*ego 30

我们对上一个项目有类似的要求:GAE后端与GWT前端和Android/iPhone客户端.此外,我们不想存储用户凭据.

所以我们选择使用OpenID,遗憾的是它是Web标准并且不能很好地与移动设备配合使用,但是可行.

在GAE方面,我们只启用了联合登录,它为我们提供了OpenID.

在移动设备上,当用户需要登录时,我们会向他们提供一个OpenID身份验证器列表(Google,Yahoo等).然后我们打开本机浏览器(不是嵌入式浏览器)并将用户引导到选定的OpenID身份验证站点.好处是用户的浏览器通常已经记住了用户名/密码,因此这一步只需要用户按一个按钮.

这一切都非常简单.现在这里是棘手的部分:用户确认登录后,OpenID重定向回我们的GAE返回URL(您需要在提出请求时提供此URL).在此网址上,我们创建了一个自定义网址,例如:

yourappname://usrname#XXXYYYZZZ
Run Code Online (Sandbox Code Playgroud)

其中XXXYYYZZZZ是身份验证令牌.我们从返回页面获取此令牌,并将其存储为ACSID cookie:我们使用一些JSP来读取此cookie并将其包装到上面的自定义URL中.

然后我们注册我们的Android和iPhone应用程序来处理yourappname://URL,这样当用户cliskc这个链接时,我们的应用程序被调用并且链接被传递给它.我们从此链接中提取用户名和令牌,我们在对GAE后端的REST请求中使用它.

如果您还有其他问题,我很乐意更新这篇文章.

更新:

生产AppEngine上的用户会话cookie被命名ACSID,而在开发AppEngine服务器上它被命名dev_appserver_login.


Igo*_*nok 12

我花了大约一个星期的时间来找到一个合适的,现代的方式 - 没有网络浏览器和使用Android客户经理.

如果您想使用Google帐户和AccountManager识别用户,您可以:

  1. 通过后台线程上的AccountManager将其令牌发送到Google通讯录(身份验证令牌类型为"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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 通过安全通道将UserToken传递给服务器.

  3. 使用gdata库(Google Data API库)通过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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. Google令牌可能会过期(通常在一小时后),因此如果您未能在服务器上验证令牌,则必须将响应发送回客户端,使令牌无效并获取新令牌.使用帐户管理器使令牌无效:

    public void invalidateUserToken(Context context, String token)
    {
        AccountManager accountManager = AccountManager.get(context);
        accountManager.invalidateAuthToken("com.google", token);
    }
    
    Run Code Online (Sandbox Code Playgroud)