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

Posted

技术标签:

【中文标题】使用 Smack 集成 facebook 聊天时 SASL 身份验证失败【英文标题】:SASL Authentication failed while integrating facebook chat using Smack 【发布时间】:2011-03-31 10:16:11 【问题描述】:

我正在尝试使用 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... 可以叫我看看有什么问题吗

【问题讨论】:

嘿任何人都可以提出一个解决方案请...运行超时 【参考方案1】:

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

例如

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

变成

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

【讨论】:

【参考方案2】:

Ignite 有一个巨大的线程来处理这个问题。您可能想看看它,因为有几种适用于 Java 和 android 的解决方案似乎可行。

【讨论】:

是的,我尝试了那里给出的所有解决方案,但都没有奏效...在论坛上发布了问题,但没有回复【参考方案3】:

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

我已经成功使用了这里提供的类

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

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

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

【讨论】:

【参考方案4】:

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;



【讨论】:

以上是关于使用 Smack 集成 facebook 聊天时 SASL 身份验证失败的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 smack 连接 facebook 聊天时出现此错误

如何在使用 Smack 发送聊天时检测错误

在黑莓上验证 Facebook 聊天时遇到问题

用于 Facebook 聊天的 Asmack 不适用于 PrivacyListManager

在与 Smack 4.2 重新连接后发送离线消息时,经过身份验证的侦听器出现异常

使用 Ejabberd 和 Smack for Android 创建群聊功能的正确方法是啥?