如何进行身份验证,以谷歌Talk与使用啪API的AccountManager的身份验证令牌?

问题描述:

这个问题是相似的:Authenticate以谷歌通话(XMPP,啪)使用的authToken

  1. 我有android.accounts.AccountManager类及其方法来获得身份验证令牌的谷歌帐户:

  1. I have android.accounts.AccountManager class and its methods to get authentication token for Google account:

public AccountManagerFuture<Bundle> getAuthToken (Account account,
       String authTokenType, Bundle options, Activity activity,
       AccountManagerCallback<Bundle> callback, Handler handler)

  • 我知道如何prepare验证XML:

  • I know how to prepare authentication XML:

    jidAndToken ="\0" + UTF8(YOURUSERNAME@gmail.com) + "\0" + Auth
    

    (其中,\ 0意在与零值的单个八位字节)。在最初的SASL身份验证使用这样的:

    (where "\0" is intended to be a single octet with value zero). Use this in the initial SASL auth:

    <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' 
          mechanism='X-GOOGLE-TOKEN'>Base64(jidAndToken)</auth>
    


  • 但我没把它与啪API集成像有人做这里的Facebook聊天:XMPP与Java Asmack库支持X-FACEBOOK平台

    But I failed to integrate it with Smack API like someone did for facebook chat here: XMPP with Java Asmack library supporting X-FACEBOOK-PLATFORM

    有人能帮助我吗?

    维杰,

    您code帮了我很多的感谢!我张贴在这里提出我的解决方案使用的AccountManager登录到谷歌谈的问题。到目前为止,我还没有找到一个完整的解决方案在那里,但我已经开发了我的基于上述code和修正了几行,不工作。

    Your code helped me a lot thanks! I am posting here to offer my solution to the problem of using AccountManager to log into Google talk. So far I have not found a full solution out there, but I have developed mine based on the above code and correcting a few lines that do not work.

    有两个部分到该溶液中。第一种是基于上述想法和code。它是制造SASLMechanism的子类:

    There are two parts to the solution. The first is based on the above idea and code. It is to create a subclass of SASLMechanism:

    import java.io.IOException;
    import java.net.URLEncoder;
    
    import org.jivesoftware.smack.SASLAuthentication;
    import org.jivesoftware.smack.XMPPException;
    import org.jivesoftware.smack.packet.Packet;
    import org.jivesoftware.smack.sasl.SASLMechanism;
    
    import android.util.Base64;
    import android.util.Log;
    
    public class GTalkOAuth2 extends SASLMechanism {
    public static final String NAME="X-GOOGLE-TOKEN";
    
    
    public GTalkOAuth2(SASLAuthentication saslAuthentication) {
        super(saslAuthentication);
    }
    
    @Override
    protected String getName() {
        return NAME;
    }
    
    static void enable() { }
    
    @Override
    protected void authenticate() throws IOException, XMPPException
    {
        String authCode = password;
        String jidAndToken = "\0" + URLEncoder.encode( authenticationId, "utf-8" ) + "\0" + authCode;
    
        StringBuilder stanza = new StringBuilder();
        stanza.append( "<auth mechanism=\"" ).append( getName() );
        stanza.append( "\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" );
        stanza.append( new String(Base64.encode( jidAndToken.getBytes( "UTF-8" ), Base64.DEFAULT ) ) );
    
        stanza.append( "</auth>" );
    
        Log.v("BlueTalk", "Authentication text is "+stanza);
        // Send the authentication to the server
        getSASLAuthentication().send( new Auth2Mechanism(stanza.toString()) );
    }
    
    public class Auth2Mechanism extends Packet {
        String stanza;
        public Auth2Mechanism(String txt) {
            stanza = txt;
        }
        public String toXML() {
            return stanza;
        }
    }
    
    /**
     * Initiating SASL authentication by select a mechanism.
     */
    public class AuthMechanism extends Packet {
        final private String name;
        final private String authenticationText;
    
        public AuthMechanism(String name, String authenticationText) {
            if (name == null) {
                throw new NullPointerException("SASL mechanism name shouldn't be null.");
            }
            this.name = name;
            this.authenticationText = authenticationText;
        }
    
        public String toXML() {
            StringBuilder stanza = new StringBuilder();
            stanza.append("<auth mechanism=\"").append(name);
            stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
            if (authenticationText != null &&
                    authenticationText.trim().length() > 0) {
                stanza.append(authenticationText);
            }
            stanza.append("</auth>");
            return stanza.toString();
        }
        }
    }
    

    的第二部分是利用它。最重要的事情,没有其他的例子给我的是,从的AccountManager系统得到令牌时,令牌类型不是啊,但邮件。当时的想法是在那里的例子做与谷歌的服务器直接沟通,以获得令牌而不是从的AccountManager请求它。把它们放在一起给,你需要做以下的事情在你的驱动程序code。创建一个函数来获取令牌:

    The second part is the use of it. The big thing that no other example gave me is that when getting the token from the AccountManager system, the token type is not "ah" but "mail". The idea was out there in examples doing a direct communication with google servers to get the token but not in requesting it from AccountManager. Putting them together gives that you need to do the following in your driver code. Create a function to get the token:

    public String getAuthToken(String name)
    {
        Context context = getApplicationContext();
        Activity activity = this;
        String retVal = "";
        Account account = new Account(name, "com.google");
        AccountManagerFuture<Bundle> accFut = AccountManager.get(context).getAuthToken(account, "mail", null, activity, null, null);
        try
        {
            Bundle authTokenBundle = accFut.getResult();
            retVal = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
        }
        catch (OperationCanceledException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (AuthenticatorException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return retVal;
    }
    

    和确保正确的SASL系统将用于以后再调用它:

    And then call it after making sure the right SASL system will be used:

    SASLAuthentication.registerSASLMechanism( GTalkOAuth2.NAME, GTalkOAuth2.class );
    SASLAuthentication.supportSASLMechanism( GTalkOAuth2.NAME, 0 );
    config.setSASLAuthenticationEnabled(true);
    
    String saslAuthString = getAuthToken(acct.name);
    connection = new XMPPConnection(config);
    try {
        connection.connect();
        connection.login(name, saslAuthString);
    } catch (XMPPException e) {
        // Most likely an expired token
        // Invalidate the token and start over. There are example of this available
    }
    

    快乐谷歌会说话!

    Happy Google Talking!