2011-09-09 12 views
8

Questa domanda è simile a: Authenticate to Google Talk (XMPP, Smack) using an authTokenCome autenticarsi a Google Talk con il token di autenticazione di AccountManager utilizzando l'API Smack?

  1. ho classe android.accounts.AccountManager ed i suoi metodi per ottenere token di autenticazione per conto di Google:

    public AccountManagerFuture<Bundle> getAuthToken (Account account, 
         String authTokenType, Bundle options, Activity activity, 
         AccountManagerCallback<Bundle> callback, Handler handler) 
    
  2. so come preparare l'autenticazione XML :

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

    (dove "\ 0" è destinato ad essere un singolo ottetto con valore zero). Utilizzare questo nel auth SASL iniziale:

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


Ma non è riuscito a integrarlo con Smack API come qualcuno ha fatto per Facebook Chat qui: XMPP with Java Asmack library supporting X-FACEBOOK-PLATFORM

qualcuno può aiutarmi?

+0

L'ho già visto, ma non l'ho mai provato. Ti dispiacerebbe postare il tuo codice in modo che io possa provare a farlo da solo e forse troverò una soluzione. Grazie – Guillaume

risposta

1

So che questo thread è un po 'vecchio, ma ho pensato di dare una mano ... Quindi ecco la mia classe che sembra funzionare con il collegamento a Gtalk usando il meccanismo di token. sinceramente, preferirei andare con oauth2 .. ma questo sembra funzionare bene. Assicurati che il tuo nome utente è come e dovrebbe funzionare:

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

Buona fortuna.

8

Vijay,

Il codice mi ha aiutato molto, grazie! Sto postando qui per offrire la mia soluzione al problema dell'utilizzo di AccountManager per accedere a Google Talk. Finora non ho trovato una soluzione completa, ma ho sviluppato la mia basata sul codice precedente e correggendo alcune righe che non funzionano.

Ci sono due parti per la soluzione. Il primo è basato sull'idea e sul codice di cui sopra. Si tratta di creare una sottoclasse di 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 seconda parte è l'uso di esso. La cosa importante che nessun altro esempio mi ha dato è che quando si ottiene il token dal sistema AccountManager, il tipo di token non è "ah" ma "mail". L'idea era là fuori in alcuni esempi facendo una comunicazione diretta con i server di google per ottenere il token ma non per richiederlo da AccountManager. Metterli insieme ti dà la necessità di fare quanto segue nel codice del driver. Creare una funzione per ottenere il 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; 
} 

E poi chiamarlo dopo essersi assicurati verrà utilizzato il sistema di SASL destra:

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 
} 

Felice Google Parlare!

+0

Sto usando questo codice, ma non sono riuscito a risolvere il mio problema. ancora non ricevo risposta dal server. –

Problemi correlati