简体   繁体   English

如何使用Smack API使用AccountManager的身份验证令牌对Google Talk进行身份验证?

[英]How to authenticate to Google Talk with AccountManager's authentication token using Smack API?

This question is similar to: Authenticate to Google Talk (XMPP, Smack) using an authToken 此问题类似于: 使用authToken对Google Talk(XMPP,Smack)进行身份验证

  1. I have android.accounts.AccountManager class and its methods to get authentication token for Google account: 我有android.accounts.AccountManager类及其获取Google帐户身份验证令牌的方法:

     public AccountManagerFuture<Bundle> getAuthToken (Account account, String authTokenType, Bundle options, Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) 
  2. I know how to prepare authentication XML: 我知道如何准备身份验证XML:

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

    (where "\\0" is intended to be a single octet with value zero). (其中“\\ 0”旨在是一个值为零的单个八位字节)。 Use this in the initial SASL auth: 在最初的SASL auth中使用它:

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


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 但是我无法将其与Smack API集成,就像有人在Facebook聊天一样: XMPP与Java Asmack库支持X-FACEBOOK-PLATFORM

Can someone help me? 有人能帮我吗?

Vijay, 维杰,

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. 我在这里发帖是为了解决使用AccountManager登录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. 到目前为止,我还没有找到完整的解决方案,但我已经根据上面的代码开发了我的,并纠正了几行不起作用。

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: 它是创建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();
    }
    }
}

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". 没有其他例子给我的重要事情是,当从AccountManager系统获取令牌时,令牌类型不是“啊”而是“邮件”。 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. 这个想法是在与谷歌服务器直接通信以获取令牌但不从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;
}

And then call it after making sure the right SASL system will be used: 然后在确保使用正确的SASL系统后调用它:

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! 快乐的谷歌说话!

I know this thread is a bit old, but I thought I'd help out... So here's my class which seems to work with smack connecting to Gtalk using the token mechanism. 我知道这个帖子有点旧,但我想我会帮帮忙...所以这是我的课程似乎与使用令牌机制连接到Gtalk的smack一起工作。 truthfully, i'd rather go with oauth2 .. but this seems to work ok. 说实话,我宁愿和oauth2一起去..但这似乎工作正常。 Make sure your username is like "<your_user>@gmail.com" and it should work: 确保您的用户名像"<your_user>@gmail.com" ,它应该有效:

public class GoogleTalkAuthentication extends SASLMechanism
{
    static
    {
        SASLAuthentication.registerSASLMechanism( "X-GOOGLE-TOKEN", GoogleTalkAuthentication.class );
        SASLAuthentication.supportSASLMechanism( "X-GOOGLE-TOKEN", 0 );
    }

    public GoogleTalkAuthentication( SASLAuthentication saslAuthentication )
    {
        super( saslAuthentication );
    }

    @Override
    protected String getName()
    {
        return "X-GOOGLE-TOKEN";
    }

    @Override
    public void authenticate( String username, String host, String password ) throws IOException, XMPPException
    {
        super.authenticate( username, host, password );
    }

    @Override
    protected void authenticate() throws IOException, XMPPException
    {
        String authCode = getAuthCode( authenticationId, 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( Base64.encode( jidAndToken.getBytes( "UTF-8" ) ) );

        stanza.append( "</auth>" );

        // Send the authentication to the server
        getSASLAuthentication().send( stanza.toString() );
    }

    public static String getAuthCode( String username, String password ) throws IOException
    {
        StringBuilder urlToRead = new StringBuilder();
        urlToRead.append( "https://www.google.com/accounts/ClientLogin?accountType=GOOGLE&service=mail&" );
        urlToRead.append( "Email=" + username + "&" );
        urlToRead.append( "Passwd=" + password );

        URL url = new URL( urlToRead.toString() );
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod( "GET" );

        BufferedReader rd = new BufferedReader( new InputStreamReader( conn.getInputStream() ) );

        try
        {
            String line;
            while ( ( line = rd.readLine() ) != null )
            {
                if ( line.startsWith( "Auth=" ) )
                    return line.substring( 5 );
            }

            return null;
        }
        finally
        {
            rd.close();
        }
    }

    public static void main( String[] args ) throws IOException
    {
        String username = "";
        String password = "";

        String authCode = getAuthCode( username, password );
        String jidAndToken = "\0" + URLEncoder.encode( username, "utf-8" ) + "\0" + authCode;

        System.err.println( authCode );
        System.err.println( "Code:" + jidAndToken );
    }
}

Good luck. 祝好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 authToken 对 Google Talk(XMPP、Smack)进行身份验证 - Authenticate to Google Talk (XMPP, Smack) using an authToken 是否有使用AccountManager帐户在Android上对Google Data API进行身份验证的官方方法? - Is there an official way to authenticate for Google Data API on Android using AccountManager accounts? 使用AccountManager使用Google API进行身份验证 - Authenticating with Google API using AccountManager 使用OAuth和AccountManager进行身份验证 - Authenticate using OAuth and AccountManager 使用Smack API和talk.goolgle.com服务器的Android聊天 - Android chat using Smack API and talk.goolgle.com server 通过Android的AccountManager获取Microsoft Exchange身份验证令牌 - Get Microsoft Exchange Authentication token through Android's AccountManager 在Google App Engine上,我可以使用Android的AccountManager关联Google OAuth 2令牌和SACSID令牌吗? - On Google App Engine, can I relate a Google OAuth 2 Token and a SACSID token I got using Android's AccountManager? 使用AccountManager令牌进行IMAP / SMTP身份验证 - IMAP/SMTP authentication with AccountManager token 无法将简单的Java Smack连接到Google Talk - Cannot connect simple Java Smack to Google Talk 如何在我的网络应用程序中使用AccountManager中的Google令牌? (带有omniauth-google-oauth2的Rails) - How do I use Google's token from AccountManager in my web app? (Rails with omniauth-google-oauth2)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM