使用Smack集成Facebook聊天时SASL身份验证失败

时间:2011-03-31 10:16:12

标签: facebook chat smack facebook-chat

我正在尝试使用smack API集成Facebook聊天。但是我在使用摘要md5时收到错误告知身份验证失败...

这是验证码:

 SASLAuthentication.registerSASLMechanism("DIGEST-MD5", SASLDigestMD5Mechanism.class);
  SASLAuthentication.supportSASLMechanism("DIGEST-MD5", 0);

    ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222);
    connection = new XMPPConnection(config);
    config.setSASLAuthenticationEnabled(true);
    connection.connect();
    connection.login(userName, password);

下面是我运行它时出现的错误:

Exception in thread "main" SASL authentication failed using mechanism DIGEST-MD5: 
    at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:325)
    at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
    at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
    at JabberSmackAPIFacebook.login(JabberSmackAPIFacebook.java:31)
    at JabberSmackAPIFacebook.main(JabberSmackAPIFacebook.java:77)

我可以成功连接到gtalk但是没有成功的vit fb ... 可以告诉我这个问题

4 个答案:

答案 0 :(得分:1)

对我而言,解决方案是在没有DNS SRV的情况下调用login()而不是Google Talk服务时,不包括用户名中的主机部分。这也是described in the ignite forums.

E.g。

connection.login("user@jabber.org", "password", "resource");

变为

connection.login("user", "password", "resource");

答案 1 :(得分:0)

Ignite有一个巨大的主题可以处理这个问题。您可能希望看一下它,因为有几种解决方案可供Java和Android使用。

答案 2 :(得分:0)

我已成功使用DIGEST-MD5连接到facebook,您发布的代码看起来不错。 但是我们仍然需要检查SASLDigestMD5Mechanism类的内容

我已使用此处提供的课程成功

http://community.igniterealtime.org/message/200878#200878

此外,您必须注意,在DIGEST-MD5机制中,您必须使用 facebook用户名登录,而不是使用电子邮件地址登录。默认情况下,Facebook帐户没有用户名,你必须创建一个fisrt,你可以在这里检查:

http://www.facebook.com/username/

答案 3 :(得分:0)

<强> MainActivity.java

public class MainActivity extends Activity {

XMPPConnection xmpp;
ArrayList<HashMap<String, String>> friends_list;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Session.openActiveSession(this, true, new StatusCallback() {

        @Override
        public void call(Session session, SessionState state, Exception exception) {

            if ( session.isOpened()){
                new testLoginTask().execute();
            }
        }
    });

}

private class testLoginTask extends AsyncTask<Void, Void, Void>{

    @Override
    protected Void doInBackground(Void... params) {

        testLogin();

        return null;
    }

}

private void testLogin(){

    ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
    config.setSASLAuthenticationEnabled(true);
    config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
    config.setDebuggerEnabled(true);


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        config.setTruststoreType("AndroidCAStore");
        config.setTruststorePassword(null);
        config.setTruststorePath(null);
    } else {
        config.setTruststoreType("BKS");
        String path = System.getProperty("javax.net.ssl.trustStore");
        if (path == null)
            path = System.getProperty("java.home") + File.separator + "etc"
                                            + File.separator + "security" + File.separator
                                            + "cacerts.bks";
        config.setTruststorePath(path);
    }


    xmpp = new XMPPConnection(config);
    SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM",SASLXFacebookPlatformMechanism.class);
    SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);

    try {
        xmpp.connect();
        Log.i("XMPPClient","Connected to " + xmpp.getHost());

    } catch (XMPPException e1) {
        Log.i("XMPPClient","Unable to " + xmpp.getHost());

        e1.printStackTrace();
    }
    try {


        String apiKey = Session.getActiveSession().getApplicationId();
        String sessionKey = Session.getActiveSession().getAccessToken();
        String sessionSecret = "replace with your app secret key";

        xmpp.login(apiKey + "|" + sessionKey, sessionSecret , "Application");

        Log.i("XMPPClient"," its logined ");

        Log.i("Connected",""+xmpp.isConnected());

        if ( xmpp.isConnected()){
            Presence presence = new Presence(Presence.Type.available);
            xmpp.sendPacket(presence);

        }

    } catch (XMPPException e) {
        e.printStackTrace();
    }  
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}

<强> SASLXFacebookPlatformMechanism.java

public class SASLXFacebookPlatformMechanism extends SASLMechanism{

private static final String NAME              = "X-FACEBOOK-PLATFORM";
private String              apiKey            = "";
private String              accessToken       = "";

/**
 * Constructor.
 */
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication) {
    super(saslAuthentication);
}

@Override
protected void authenticate() throws IOException, XMPPException {
    getSASLAuthentication().send(new AuthMechanism(NAME, ""));
}

@Override
public void authenticate(String apiKey, String host, String accessToken) throws IOException, XMPPException {
    if (apiKey == null || accessToken == null) {
        throw new IllegalArgumentException("Invalid parameters");
    }

    this.apiKey = apiKey;
    this.accessToken = accessToken;
    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 composedResponse = "api_key="
                + URLEncoder.encode(apiKey, "utf-8") + "&call_id=" + callId
                + "&method=" + URLEncoder.encode(method, "utf-8")
                + "&nonce=" + URLEncoder.encode(nonce, "utf-8")
                + "&access_token="
                + URLEncoder.encode(accessToken, "utf-8") + "&v="
                + URLEncoder.encode(version, "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;
}

}