连接到Facebook XMMP MD5-DIGEST的问题

时间:2011-12-16 09:45:34

标签: java android facebook

我已尝试过将Facebook与XMPP联系起来的所有事情,但我只面对过          一直有一个错误是:
 SASL身份验证使用机制DIGEST-MD5失败了我正在实现以下方法来执行此任务:

public class MySASLDigestMD5Mechanism extends SASLMechanism {

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

protected void authenticate() throws IOException, XMPPException {
    String[] mechanisms = { getName() };
    Map<String, String> props = new HashMap<String, String>();
    sc = Sasl.createSaslClient(mechanisms, null, "xmpp", hostname, props, this);

    super.authenticate();
}

public void authenticate(String username, String host, String password) throws IOException, XMPPException {
    this.authenticationId = username;
    this.password = password;
    this.hostname = host;

    String[] mechanisms = { getName() };
    Map<String,String> props = new HashMap<String,String>();
    sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, this);
    super.authenticate();
}

public void authenticate(String username, String host, CallbackHandler cbh) throws IOException, XMPPException {
    String[] mechanisms = { getName() };
    Map<String,String> props = new HashMap<String,String>();
    sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, (org.apache.harmony.javax.security.auth.callback.CallbackHandler) cbh);
    super.authenticate();
}

protected String getName() {
    return "DIGEST-MD5";
}

/*public void challengeReceived1(String challenge) throws IOException {
    // Build the challenge response stanza encoding the response text
    StringBuilder stanza = new StringBuilder();

    byte response[];
    if (challenge != null) {
        response = sc.evaluateChallenge(Base64.decode(challenge));
    } else {
        response = sc.evaluateChallenge(null);
    }

    String authenticationText="";

    if (response != null) { // fix from 3.1.1
        authenticationText = Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);
        if (authenticationText.equals("")) {
            authenticationText = "=";
        }
    }

    stanza.append("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
    stanza.append(authenticationText);
    stanza.append("</response>");

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

 public void challengeReceived(String challenge)
 throws IOException {

 byte response[];

 if (challenge != null) {
     response = sc.evaluateChallenge(Base64.decode(challenge));
 } else {
     response = sc.evaluateChallenge(new byte[0]);
 }

 Packet responseStanza;

 if (response == null) {
     responseStanza = new Response();
 } else {
     responseStanza = new Response(Base64.encodeBytes(response, Base64.DONT_BREAK_LINES));
 }

 getSASLAuthentication().send(responseStanza);

}

}

连接功能是:

     try{
        SASLAuthentication.registerSASLMechanism("DIGEST-MD5",MySASLDigestMD5Mechanism. class);

        ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222);



        config.setSASLAuthenticationEnabled(true);

        config.setRosterLoadedAtLogin (true);



        connection = new XMPPConnection(config);

        connection.connect();
        Log.d("Connect...", "Afetr Connect");
        connection.login("username@chat.facebook.com", "password");
        Log.d("done","XMPP client logged in");
    }
    catch(XMPPException ex)
    {
        Log.d("not done","in catchhhhhhhhh");
        System.out.println(ex.getMessage ());
        connection.disconnect();
    }

}
but "After connect" it gone to the ctach and give me error like : 

  SASL authentication failed using mechanism DIGEST-MD5

我搜索了所有博客并找到了相同的东西,但我不知道我在这里做错了什么..

如果有任何其他方式或解决方案连接Facebook XMPP,请帮助我        ASAP的

2 个答案:

答案 0 :(得分:5)

最后,由于no.good.at.coding代码和harism的建议,我已经能够连接到Facebook聊天。此代码是Asmack库(Android的Smack端口)的机制。对于Smack库,必须使用no.good.at.coding机制。

SASLXFacebookPlatformMechanism.java:

import java.io.IOException;
import java.io.UnsupportedEncodingException; 
import java.net.URLEncoder; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.GregorianCalendar; 
import java.util.HashMap; 
import java.util.Map;  
import org.apache.harmony.javax.security.auth.callback.CallbackHandler; 
import org.apache.harmony.javax.security.sasl.Sasl; 
import org.jivesoftware.smack.SASLAuthentication; 
import org.jivesoftware.smack.XMPPException; 
import org.jivesoftware.smack.sasl.SASLMechanism; 
import org.jivesoftware.smack.util.Base64;

public class SASLXFacebookPlatformMechanism extends SASLMechanism 
{      
    private static final String NAME              = "X-FACEBOOK-PLATFORM";      
    private String              apiKey            = "";     
    private String              applicationSecret = "";     
    private String              sessionKey        = "";      
    /**      * Constructor.      */     
    public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication)     
    {         
        super(saslAuthentication);     
    }      
    @Override     
    protected void authenticate() throws IOException, XMPPException     
    {          
        getSASLAuthentication().send(new AuthMechanism(NAME, ""));     
    }      
    @Override     
    public void authenticate(String apiKeyAndSessionKey, String host,             String applicationSecret) throws IOException, XMPPException     
    {         
        if (apiKeyAndSessionKey == null || applicationSecret == null)         
        {             
            throw new IllegalArgumentException("Invalid parameters");         
        }          
        String[] keyArray = apiKeyAndSessionKey.split("\\|", 2);         
        if (keyArray.length < 2)         
        {             
            throw new IllegalArgumentException(                     "API key or session key is not present");         }          
            this.apiKey = keyArray[0];         
            this.applicationSecret = applicationSecret;         
            this.sessionKey = keyArray[1];          
            this.authenticationId = sessionKey;         
            this.password = applicationSecret;         
            this.hostname = host;          
            String[] mechanisms = { "DIGEST-MD5" };         

            Map<String, String> props = new HashMap<String, String>();         
            this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,this);        
            authenticate();
        }      
        @Override     
        public void authenticate(String username, String host, CallbackHandler cbh)throws IOException, XMPPException     
        {         
            String[] mechanisms = { "DIGEST-MD5" };         
            Map<String, String> props = new HashMap<String, String>();         
            this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,cbh);         
            authenticate();
        }      @Override     protected String getName()

        {        
            return NAME;     
        }      
        @Override     
        public void challengeReceived(String challenge) throws IOException     
        {         
            byte[] response = null;          
            if (challenge != null)         
            {             
                String decodedChallenge = new String(Base64.decode(challenge));             
                Map<String, String> parameters = getQueryMap(decodedChallenge);              
                String version = "1.0";             
                String nonce = parameters.get("nonce");             
                String method = parameters.get("method");              
                long callId = new GregorianCalendar().getTimeInMillis();              
                String sig = "api_key=" + apiKey + "call_id=" + callId + "method=" + method + "nonce=" + nonce + "session_key=" + sessionKey + "v=" + version + applicationSecret;
                try             
                {                 
                    sig = md5(sig);             
                } 
                catch (NoSuchAlgorithmException e)             
                {                 
                    throw new IllegalStateException(e);             
                }              
                String composedResponse = "api_key=" + URLEncoder.encode(apiKey, "utf-8") + "&call_id=" + callId + "&method="+ URLEncoder.encode(method, "utf-8") + "&nonce="+ URLEncoder.encode(nonce, "utf-8")+ "&session_key="+ URLEncoder.encode(sessionKey, "utf-8") + "&v="+ URLEncoder.encode(version, "utf-8") + "&sig="+ URLEncoder.encode(sig, "utf-8");response = composedResponse.getBytes("utf-8");
                }          
                String authenticationText = "";          
                if (response != null)         
                {             
                    authenticationText = Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);         
                }          

                // Send the authentication to the server         
                getSASLAuthentication().send(new Response(authenticationText));     
                }      
        private Map<String, String> getQueryMap(String query)     
        {         
            Map<String, String> map = new HashMap<String, String>();         
            String[] params = query.split("\\&");          
            for (String param : params)         
            {             
                String[] fields = param.split("=", 2);             
                map.put(fields[0], (fields.length > 1 ? fields[1] : null));         
            }          
            return map;     
            }      
        private String md5(String text) throws NoSuchAlgorithmException,UnsupportedEncodingException     
        {         
            MessageDigest md = MessageDigest.getInstance("MD5");         
            md.update(text.getBytes("utf-8"), 0, text.length());         
            return convertToHex(md.digest());     
        }      
        private String convertToHex(byte[] data)     
        {         
            StringBuilder buf = new StringBuilder();         
            int len = data.length;          
            for (int i = 0; i < len; i++)         
            {             
                int halfByte = (data[i] >>> 4) & 0xF;             
                int twoHalfs = 0;              
                do             
                {                 
                    if (0 <= halfByte && halfByte <= 9)                 
                    {                     
                        buf.append((char) ('0' + halfByte));                 
                    }                 
                    else                 
                    {                     
                        buf.append((char) ('a' + halfByte - 10));                 
                    }                 
                    halfByte = data[i] & 0xF;             
                } 
                while (twoHalfs++ < 1);         
            }          
            return buf.toString();     
            } 
        }

使用它:

ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222); 
config.setSASLAuthenticationEnabled(true); 
XMPPConnection xmpp = new XMPPConnection(config); 
try 
{     
    SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM", SASLXFacebookPlatformMechanism.class);     
    SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);     
    xmpp.connect();     
    xmpp.login(apiKey + "|" + sessionKey, sessionSecret, "Application"); 
} 
catch (XMPPException e) 
{     
    xmpp.disconnect();     
    e.printStackTrace(); 
}

apiKey是Facebook中应用程序设置页面中给出的API密钥。 sessionKey是访问令牌的第二部分。如果令牌是这种形式,AAA | BBB | CCC,则BBB是会话密钥。 sessionSecret是使用旧的REST API和auth.promoteSession方法获得的。要使用它,需要让Http到达这个URL:

https://api.facebook.com/method/auth.promoteSession?access_token=yourAccessToken

尽管Facebook Chat文档说它需要使用你的应用程序密钥,但只有当我使用返回该REST方法的密钥时我才能使其工作。要使该方法有效,您必须在应用程序设置的“高级”选项卡中禁用“禁用不推荐使用的身份验证方法”选项。

答案 1 :(得分:3)

我解决了这个问题。我找到http://community.igniterealtime.org/thread/41080

的解决方案

Jerry Magill写了这个......

import java.io.IOException;
import java.util.HashMap;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.Sasl;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.Base64;

public class MySASLDigestMD5Mechanism extends SASLMechanism
{
    public MySASLDigestMD5Mechanism(SASLAuthentication saslAuthentication)
    {
        super(saslAuthentication);
    }

    protected void authenticate()
        throws IOException, XMPPException
    {
        String mechanisms[] = {
            getName()
        };
        java.util.Map props = new HashMap();
        sc = Sasl.createSaslClient(mechanisms, null, "xmpp", hostname, props, this);
        super.authenticate();
    }

    public void authenticate(String username, String host, String password)
    throws IOException, XMPPException
    {
        authenticationId = username;
        this.password = password;
        hostname = host;
        String mechanisms[] = {
            getName()
        };
        java.util.Map props = new HashMap();
        sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, this);
        super.authenticate();
    }

    public void authenticate(String username, String host, CallbackHandler cbh)
        throws IOException, XMPPException
    {
        String mechanisms[] = {
            getName()
        };
        java.util.Map props = new HashMap();
        sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, cbh);
        super.authenticate();
    }

    protected String getName()
    {
        return "DIGEST-MD5";
    }

    public void challengeReceived(String challenge)
        throws IOException
    {
        //StringBuilder stanza = new StringBuilder();
        byte response[];
        if(challenge != null)
            response = sc.evaluateChallenge(Base64.decode(challenge));
        else
            //response = sc.evaluateChallenge(null);
            response = sc.evaluateChallenge(new byte[0]);
        //String authenticationText = "";
        Packet responseStanza;
        //if(response != null)
        //{
            //authenticationText = Base64.encodeBytes(response, 8);
            //if(authenticationText.equals(""))
                //authenticationText = "=";

        if (response == null){
            responseStanza = new Response();
        } else {
            responseStanza = new  Response(Base64.encodeBytes(response,Base64.DONT_BREAK_LINES));   
        }
        //}
        //stanza.append("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
        //stanza.append(authenticationText);
        //stanza.append("</response>");
        //getSASLAuthentication().send(stanza.toString());
        getSASLAuthentication().send(responseStanza);
    }
}

然后从JabberSmackAPI中调用它:

public void login(String userName, String password) throws XMPPException
{       
    SASLAuthentication.registerSASLMechanism("DIGEST-MD5",MySASLDigestMD5Mechanism. class);
    ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222);

    config.setSASLAuthenticationEnabled(true);
    config.setRosterLoadedAtLogin (true);

    connection = new XMPPConnection(config);
    connection.connect();
    connection.login(userName, password);
}