2011-09-09 16 views
8

Esta pregunta es similar a: Authenticate to Google Talk (XMPP, Smack) using an authToken¿Cómo autenticarse en Google Talk con el token de autenticación de AccountManager utilizando Smack API?

  1. tengo clase android.accounts.AccountManager y sus métodos para obtener token de autenticación para la cuenta de Google:

    public AccountManagerFuture<Bundle> getAuthToken (Account account, 
         String authTokenType, Bundle options, Activity activity, 
         AccountManagerCallback<Bundle> callback, Handler handler) 
    
  2. sé cómo preparar XML autenticación :

    jidAndToken ="\0" + UTF8([email protected]) + "\0" + Auth 
    

    (donde "\ 0" pretende ser un solo octeto con valor cero). Utilice esta en la autenticación inicial SASL:

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


Pero no pudo integrarlo con API Smack como si alguien hizo por chat de facebook aquí: XMPP with Java Asmack library supporting X-FACEBOOK-PLATFORM

Alguien me puede ayudar?

+0

Miré esto antes, pero nunca lo intenté realmente. ¿Te importaría publicar tu código para poder intentarlo y quizás encuentre una solución? Gracias – Guillaume

Respuesta

1

Sé que este hilo es un poco viejo, pero pensé que ayudaría ... Así que aquí está mi clase que parece funcionar con smack conectarse a Gtalk utilizando el mecanismo de token. Sinceramente, prefiero ir con oauth2 ... pero parece que funciona bien. Asegúrese de que su nombre de usuario es como y debería funcionar:

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); 
    } 
} 

Buena suerte.

8

Vijay,

Su código me ayudó mucho, gracias! Estoy publicando aquí para ofrecer mi solución al problema de usar AccountManager para iniciar sesión en Google Talk. Hasta ahora no he encontrado una solución completa, pero he desarrollado la mía basándose en el código anterior y corrigiendo algunas líneas que no funcionan.

La solución tiene dos partes. El primero se basa en la idea y el código anteriores. Es crear una subclase de 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(); 
    } 
    } 
} 

La segunda parte es su uso. Lo más importante que ningún otro ejemplo me dio es que al obtener el token del sistema AccountManager, el tipo de token no es "ah" sino "correo". La idea estaba en ejemplos que hacen una comunicación directa con los servidores de google para obtener el token pero no al solicitarlo desde AccountManager. Poniéndolos juntos le indica que debe hacer lo siguiente en su código de controlador. Crear una función para obtener el 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; 
} 

Y luego llamarlo después de asegurarse de que se utilizará el sistema de SASL derecha:

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 
} 

feliz Google Hablar!

+0

Estoy usando este código, pero no tuve éxito para resolver mi problema. todavía no recibo respuesta del servidor. –

Cuestiones relacionadas