2012-01-25 101 views
0

我试图给Facebook聊天上我的jQuery Mobile的整合,并考虑以下 architecture远程连接失败与Facebook连接聊天

但是,当,当我开启服务器(旁遮普)上,并把必要的凭证以下在JavaScript相关的Facebook我越来越远程连接失败错误 任何人都可以告诉我什么是缺失。

JID :   [email protected] 
PASSWORD:  <FacebookPassword> 

传出在Windows &传入请求

SENT:<body rid='1283282620' xmlns='http://jabber.org/protocol/httpbind' to='chat.facebook.com' xml:lang='en' wait='300' hold='1' content='text/xml; charset=utf-8' ver='1.6' xmpp:version='1.0' xmlns:xmpp='urn:xmpp:xbosh'/> 

    RECV:<body xmlns='http://jabber.org/protocol/httpbind' type='terminate' condition='remote-connection-failed'/> 

启动服务器XP

Python twistd.py punjab 

2012-01-26 10:41:45+0530 [-] Log opened. 
2012-01-26 10:41:45+0530 [-] twistd 11.1.0 (C:\Python27\python.exe 2.7.2) starti 
ng up. 
2012-01-26 10:41:45+0530 [-] reactor class: twisted.internet.selectreactor.Selec 
tReactor. 
2012-01-26 10:41:45+0530 [-] Site starting on 5280 
2012-01-26 10:41:45+0530 [-] Starting factory <twisted.web.server.Site instance 
at 0x013A12B0> 

时,我打http://localhost:5280/http-bind我得到XEP-0124 - BOSH

条目URL

http://localhost/strophejs/facebook-chat-example/facebook.html

facebook.html

<html> 
<head> 
<script src="http://connect.facebook.net/en_US/all.js" type="text/javascript"></script> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> 
<script src="strophe.min.js" type="text/javascript"></script> 
<script src="facebook.js" type="text/javascript"></script> 
<script> 
var BOSH_SERVICE = 'http://localhost:5280/http-bind' 
var connection = null; 

function log(msg) 
{ 
    $('#log').append('<div></div>').append(document.createTextNode(msg)); 
} 

function rawInput(data) 
{ 
    log('RECV: ' + data); 
} 

function rawOutput(data) 
{ 
    log('SENT: ' + data); 
} 

function onConnect(status) 
{ 
    if (status == Strophe.Status.CONNECTING) { 
    log('Strophe is connecting.'); 
    } else if (status == Strophe.Status.CONNFAIL) { 
    log('Strophe failed to connect.'); 
    $('#connect').get(0).value = 'connect'; 
    } else if (status == Strophe.Status.DISCONNECTING) { 
    log('Strophe is disconnecting.'); 
    } else if (status == Strophe.Status.DISCONNECTED) { 
    log('Strophe is disconnected.'); 
    $('#connect').get(0).value = 'connect'; 
    } else if (status == Strophe.Status.CONNECTED) { 
    log('Strophe is connected.'); 
    connection.disconnect(); 
    } 
} 

$(document).ready(function() { 
    var access_token; 
    FB.init({ 
      appId  : 'XXXXXXXXXXX', 
      status  : true, 
      cookie  : true, 
      xfbml  : true, 
      oauth  : true, 
    }); 

    FB.login(function (response) { 
     console.log(response); 
     if (response.authResponse) { 
      access_token = response.authResponse.accessToken; 
      console.log(access_token); 
     } else { 
      alert('User is logged out'); 
     } 
    },{scope: 'email,user_online_presence,friends_online_presence,xmpp_login'}); 

    connection = new Strophe.Connection(BOSH_SERVICE); 
    connection.rawInput = rawInput; 
    connection.rawOutput = rawOutput; 

    $('#connect').bind('click', function() { 
    var button = $('#connect').get(0); 
    if (button.value == 'connect') { 
     button.value = 'disconnect'; 

     connection.facebookConnect($('#jid').get(0).value, 
        onConnect, 
        300, 
        1, 
        'XXXXXXXXXX' , /*app id*/ 
        'XXXXXXXXXXXXXXXXXX',/*secret key*/ 
        access_token); 
    } else { 
     button.value = 'connect'; 
     connection.disconnect(); 
    } 
    }); 
}); 
</script> 
</head> 

<body> 
<div id="fb-root"></div> 
<div id='login' style='text-align: center'> 
     <form name='cred'> 
     <label for='jid'>JID:</label> 
     <input type='text' id='jid'> 
     <label for='pass'>Password:</label> 
     <input type='password' id='pass'> 
     <input type='button' id='connect' value='connect'> 
     </form> 
    </div> 
    <hr> 
    <div id='log'></div> 
</body> 
</html> 

facebook.js

/* 
    @author: Ruben J Garcia <[email protected]> 
    @version: 1.0 

    This program is distributed under the terms of the MIT license. 
    Please see the LICENSE file for details. 

    Copyright 2006-2008, OGG, LLC 
*/ 

/** 
* Split a string by string 
* @param delimiter string The boundary string. 
* @param string string The input string. 
* @param limit int[optional] If limit is set and positive, the returned array will contain 
*  a maximum of limit elements with the last 
*  element containing the rest of string. 
* 
*  If the limit parameter is negative, all components 
*  except the last -limit are returned. 
* 
*  If the limit parameter is zero, then this is treated as 1. 
* 
* @returns array If delimiter is an empty string (""), 
*  explode will return false. 
*  If delimiter contains a value that is not 
*  contained in string and a negative 
*  limit is used, then an empty array will be 
*  returned. For any other limit, an array containing 
*  string will be returned. 
*/ 
function explode(delimiter, string, limit) { 
     var emptyArray = { 0: '' }; 

     // third argument is not required 
     if (arguments.length < 2 || 
      typeof arguments[0] == 'undefined' || typeof arguments[1] == 'undefined') { 
      return null; 
     } 

     if (delimiter === '' || delimiter === false || 
      delimiter === null) { 
      return false; 
     } 

     if (typeof delimiter == 'function' || typeof delimiter == 'object' || 
      typeof string == 'function' || typeof string == 'object') { 
       return emptyArray;  
     } 

     if (delimiter === true) { 
      delimiter = '1'; 
     } 

     if (!limit) { 
      return string.toString().split(delimiter.toString()); 
     } else { 
      // support for limit argument   
      var splitted = string.toString().split(delimiter.toString()); 
      var partA = splitted.splice(0, limit - 1); 
      var partB = splitted.join(delimiter.toString()); 
      partA.push(partB); 
      return partA; 
     } 
}; 

/** 
* Handler for X-FACEBOOK-PLATFORM SASL authentication. 
* 
* @param (XMLElement) elem - The challenge stanza. 
* 
* @returns false to remove the handler. 
*/ 
Strophe.Connection.prototype._sasl_challenge1_fb = function (elem) 
    { 
     var challenge = Base64.decode(Strophe.getText(elem)); 
     var nonce = ""; 
     var method = ""; 
     var version = ""; 

     // remove unneeded handlers 
     this.deleteHandler(this._sasl_failure_handler); 

     var challenges = explode("&", challenge); 
     for(i=0; i<challenges.length; i++) 
     { 
      map = explode("=", challenges[i]); 
      switch (map[0]) 
      { 
       case "nonce": 
        nonce = map[1]; 
        break; 
       case "method": 
        method = map[1]; 
        break; 
       case "version": 
        version = map[1]; 
        break; 
      } 
     } 

     var responseText = ""; 

     responseText += 'api_key=' + this.apiKey; 
     responseText += '&call_id=' + (Math.floor(new Date().getTime()/1000)); 
     responseText += '&method=' + method; 
     responseText += '&nonce=' + nonce; 
     responseText += '&access_token=' + this.sessionKey; 
     responseText += '&v=' + '1.0'; 
     responseText += '&sig=' + MD5.hexdigest(responseText.replace(/&/g,"")+this.secretKey); 

     this._sasl_challenge_handler = this._addSysHandler(
      this._sasl_challenge2_cb.bind(this), null, 
      "challenge", null, null); 
     this._sasl_success_handler = this._addSysHandler(
      this._sasl_success_cb.bind(this), null, 
      "success", null, null); 
     this._sasl_failure_handler = this._addSysHandler(
      this._sasl_failure_cb.bind(this), null, 
      "failure", null, null); 

     this.send($build('response', { 
      xmlns: Strophe.NS.SASL 
     }).t(Base64.encode(responseText)).tree()); 

     return false; 
}; 

/** 
* Handler for initial connection request with Facebokk. 
* 
* This handler is used to process the initial connection request 
* response from the BOSH server. It is used to set up authentication 
* handlers and start the authentication process. 
* 
* SASL authentication will be attempted if available, otherwise 
* the code will fall back to legacy authentication. 
* 
* @param (Strophe.Request) req - The current request. 
*/ 
Strophe.Connection.prototype._connect_fb = function (req) { 
     Strophe.info("_connect_fb was called"); 

     this.connected = true; 
     var bodyWrap = req.getResponse(); 
     if (!bodyWrap) { return; } 

     this.xmlInput(bodyWrap); 
     this.rawInput(Strophe.serialize(bodyWrap)); 

     var typ = bodyWrap.getAttribute("type"); 
     var cond, conflict; 
     if (typ !== null && typ == "terminate") { 
      // an error occurred 
      cond = bodyWrap.getAttribute("condition"); 
      conflict = bodyWrap.getElementsByTagName("conflict"); 
      if (cond !== null) { 
       if (cond == "remote-stream-error" && conflict.length > 0) { 
        cond = "conflict"; 
       } 
       this._changeConnectStatus(Strophe.Status.CONNFAIL, cond); 
      } else { 
       this._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown"); 
      } 
      return; 
     } 

     // check to make sure we don't overwrite these if _connect_fb is 
     // called multiple times in the case of missing stream:features 
     if (!this.sid) { 
      this.sid = bodyWrap.getAttribute("sid"); 
     } 
     if (!this.stream_id) { 
      this.stream_id = bodyWrap.getAttribute("authid"); 
     } 
     var wind = bodyWrap.getAttribute('requests'); 
     if (wind) { this.window = wind; } 
     var hold = bodyWrap.getAttribute('hold'); 
     if (hold) { this.hold = hold; } 
     var wait = bodyWrap.getAttribute('wait'); 
     if (wait) { this.wait = wait; } 

     var mechanisms = bodyWrap.getElementsByTagName("mechanism"); 
     var i, mech, auth_str, hashed_auth_str, xfacebook; 
     if (mechanisms.length == 0) { 
      // we didn't get stream:features yet, so we need wait for it 
      // by sending a blank poll request 
      var body = this._buildBody(); 
      this._requests.push(
       new Strophe.Request(body.tree(), 
            this._onRequestStateChange.bind(this) 
             .prependArg(this._connect_cb.bind(this)), 
            body.tree().getAttribute("rid"))); 
      this._throttledRequestHandler(); 
      return; 
     } else { 
      for (i = 0; i < mechanisms.length; i++) { 
       mech = Strophe.getText(mechanisms[i]); 
       if (mech == 'X-FACEBOOK-PLATFORM') { 
        xfacebook = true; 
        break; 
       } 
      } 
     } 

     if (!xfacebook) { 
      return; 
     } 

     this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); 
     this._sasl_challenge_handler = this._addSysHandler(
      this._sasl_challenge1_fb.bind(this), null, 
      "challenge", null, null); 
     this._sasl_failure_handler = this._addSysHandler(
      this._sasl_challenge1_fb.bind(this), null, 
      "failure", null, null); 

     this.send($build("auth", { 
      xmlns: Strophe.NS.SASL, 
      mechanism: "X-FACEBOOK-PLATFORM" 
     }).tree()); 
}; 

/** 
* Starts the connection process with facebok XMPP Chat Server. 
* 
* As the connection process proceeds, the user supplied callback will 
* be triggered multiple times with status updates. The callback 
* should take two arguments - the status code and the error condition. 
* 
* The status code will be one of the values in the Strophe.Status 
* constants. The error condition will be one of the conditions 
* defined in RFC 3920 or the condition 'strophe-parsererror'. 
* 
* Please see XEP 124 for a more detailed explanation of the optional 
* parameters below. 
* 
* @param (String) jid - The user's JID. It must be [email protected], 
*  where facebook id is the number id of the facebook profile 
* @param (Function) callback The connect callback function. 
* @param (Integer) wait - The optional HTTPBIND wait value. This is the 
*  time the server will wait before returning an empty result for 
*  a request. The default setting of 60 seconds is recommended. 
*  Other settings will require tweaks to the Strophe.TIMEOUT value. 
* @param (Integer) hold - The optional HTTPBIND hold value. This is the 
*  number of connections the server will hold at one time. This 
*  should almost always be set to 1 (the default). 
* @param apiKey The API key of our Facebook Application 
* @param secretKey The secret key of our Facebook Application 
* @param sessionKey The actual session key for the user who we are attempting to log in 
*/ 
Strophe.Connection.prototype.facebookConnect = function (jid, callback, wait, hold, apiKey, secretKey, sessionKey){ 
    this.jid = jid; 
    this.connect_callback = callback; 
    this.disconnecting = false; 
    this.connected = false; 
    this.authenticated = false; 
    this.errors = 0; 
    this.apiKey = apiKey; 
    this.secretKey = secretKey; 
    this.sessionKey = sessionKey; 

    this.wait = wait || this.wait; 
    this.hold = hold || this.hold; 

    // parse jid for domain and resource 
    this.domain = Strophe.getDomainFromJid(this.jid); 

    // build the body tag 
    var body = this._buildBody().attrs({ 
     to: this.domain, 
     "xml:lang": "en", 
     wait: this.wait, 
     hold: this.hold, 
     content: "text/xml; charset=utf-8", 
     ver: "1.6", 
     "xmpp:version": "1.0", 
     "xmlns:xmpp": Strophe.NS.BOSH 
    }); 

    this._changeConnectStatus(Strophe.Status.CONNECTING, null); 

    this._requests.push(
     new Strophe.Request(body.tree(), 
          this._onRequestStateChange.bind(
          this, this._connect_fb.bind(this)), 
          body.tree().getAttribute("rid"))); 
    this._throttledRequestHandler(); 
}; 

请有人建议我用正确的方法整合Facebook聊天

回答

0

您需要检查几件事情:

  • 旁遮普返回的错误是远程连接失败。这意味着它无法打开chat.facebook.com的连接。您的旁遮普日志似乎不匹配,因为您没有任何尝试连接到Facebook。
  • 您可能会伤害跨域问题,这可能是您的客户端无法连接到旁遮普邦的原因。旁遮普正在端口5280上运行,您的客户端在端口80上运行。这是不同的服务,您的浏览器可能会阻止从端口80上的客户端连接回端口5280.请检查您的Javascript浏览器日志。我预计会出现一个错误。
  • Facebook在使用代理时不支持标准认证。您将需要一个支持X-FACEBOOK-PLATFORM SASL认证机制的库。见:http://developers.facebook.com/docs/chat/
+0

我需要旁遮普吗?还是我需要ejabberd? – Hunt

2

这是一个非常古老的问题,但我只是面临同样的问题,并张贴这个万一任何人面临同样的问题。

我没有安装pyopenssl,并安装它立即解决了问题。

+0

是的,就像HyperGeek提到的那样,安装[pyopenssl](https://launchpad.net/pyopenssl)为我修复了它! – RamRovi