整合Facebook聊天

Sea*_*ock 16 c# facebook xmpp x-facebook-platform

我已经编写了一个程序来集成在C#中的Facebook用户聊天,但是我总是<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>在将响应发送到服务器之后得到.

我检查了API密钥和App秘密,两者都是正确的.看起来我将一些错误的参数传递给服务器.

这是我的代码.

private void GetDetailsButton_Click(object sender, EventArgs e)
{
     TcpClient FacebookClient = new TcpClient();
     FacebookClient.Connect("chat.facebook.com", 5222);
     NetworkStream myns = FacebookClient.GetStream();

     string xml = "<?xml version='1.0'?>" +
     "<stream:stream " +
     "id='1' " +
     "to='chat.facebook.com' " +
     "xmlns='jabber:client' " +
     "xmlns:stream='http://etherx.jabber.org/streams' " +
     "version='1.0' >";

     StreamWriter mySw = new StreamWriter(myns);
     mySw.WriteLine(xml);  //sending initial request
     mySw.Flush();

     byte[] serverResponseByte = new byte[1024];
     int myBytesRead = 0;
     StringBuilder myResponseAsSB = new StringBuilder();

     //reading response from the server to see the supported authentication methods 
     do
     {
            myBytesRead = myns.Read(serverResponseByte, 0, serverResponseByte.Length);
            myResponseAsSB.Append(System.Text.Encoding.UTF8.GetString(serverResponseByte, 0, myBytesRead));

     } while (myns.DataAvailable);


     myResponseAsSB.Clear();

     xml = "<auth " +
     "xmlns='urn:ietf:params:xml:ns:xmpp-sasl' " +
     "mechanism='X-FACEBOOK-PLATFORM'  />";

     mySw.WriteLine(xml);
     mySw.Flush();   //sending response to server to use X-FACEBOOK-PLATFORM


     //reading challenge send by the server
     do
     {
          myBytesRead = myns.Read(serverResponseByte, 0, serverResponseByte.Length);
          myResponseAsSB.Append(System.Text.Encoding.UTF8.GetString(serverResponseByte, 0, myBytesRead));

     } while (myns.DataAvailable);


     myResponseAsSB.Replace("<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">", "");
     myResponseAsSB.Replace("</challenge>", "");

     //converting challenge string to normal string
     byte[] myregularstrigbytes = Convert.FromBase64String(myResponseAsSB.ToString());
     string myregularstring = System.Text.Encoding.UTF8.GetString(myregularstrigbytes);


     //I've hardcoded the accesstoken here for testing purpose. 
     string SessionKey = AccessToken.Split('|')[1]; 

     string response = ComposeResponse(myregularstring);

     byte[] myResponseByte = Encoding.UTF8.GetBytes(response.ToString());

     string myEncodedResponseToSend = Convert.ToBase64String(myResponseByte);
     xml = String.Format("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">{0}</response>", myEncodedResponseToSend);
     mySw.WriteLine(xml);
     mySw.Flush();   //sending the response to the server with my parameters

     myResponseAsSB.Clear();

     //checking if authentication succeed 
     do
     {
          myBytesRead = myns.Read(serverResponseByte, 0, serverResponseByte.Length);
          myResponseAsSB.Append(System.Text.Encoding.UTF8.GetString(serverResponseByte, 0, myBytesRead));

     } while (myns.DataAvailable);

     MessageBox.Show(myResponseAsSB.ToString());

}

    private string ComposeResponse(string serverresponse)
    {
         string version = serverresponse.Split('&')[0].Split('=')[1];
         string method = serverresponse.Split('&')[1].Split('=')[1];
         string nonce = serverresponse.Split('&')[2].Split('=')[1];
         string SessionKey = AccessToken.Split('|')[1];

         long callId = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;

         string sig = "api_key=" + appId
         + "call_id=" + callId
         + "method=" + method
         + "nonce=" + nonce
         + "session_key=" + SessionKey
         + "v=" + "1.0"
         + AppSecret;

         MD5 md = MD5.Create();
         var hash = md.ComputeHash(Encoding.UTF8.GetBytes(sig));

         sig = hash.Aggregate("", (current, b) => current + b.ToString("x2"));

         return "api_key=" + HttpUtility.UrlEncode(appId)
         + "&call_id=" + HttpUtility.UrlEncode(callId)
         + "&method=" + HttpUtility.UrlEncode(method)
         + "&nonce=" + HttpUtility.UrlEncode(nonce)
         + "&session_key=" + HttpUtility.UrlEncode(SessionKey)
         + "&v=" + HttpUtility.UrlEncode("1.0")
         + "&sig=" + HttpUtility.UrlEncode(sig);

    }
Run Code Online (Sandbox Code Playgroud)

在C#X-FACEBOOK-PLATFORM中评论了这篇文章Facebook Chat Authentication,我的应用程序类型是Native/Desktop.

有人能指出我正确的方向吗?

编辑: 我认为问题是在创建签名时,有没有办法验证创建的签名?

编辑1:根据此SO答案,访问令牌包含第一个|之后的会话密钥 性格,我可以找到| 字符直到2天前,但现在我找不到| 访问令牌中的字符,它真的很奇怪,所以我现在如何找到会话密钥?(或者我现在应该去睡觉了.)

编辑2:奇怪的是我总是<appId>|<sessionKey>|<digest>以本机/桌面应用程序的形式获得访问令牌.我进一步搜索并发现会话密钥需要从auth.promoteSession legacy api中提取并使用HttpUtility.UrlEncode而不是编码参数HttpUtility.HtmlEncode.

现在我已经硬编码了访问令牌(在访问令牌调试器中验证了它),会话密钥,应用密钥和应用秘密我仍然得到相同的错误<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>

编辑3:我一直在敲打我的头一个星期仍然没有用,但今天我在文档中发现了一个更新说Note that this needs to be over TLS (Transport Layer Security) or you'll get an error. 我想我需要相应地修改我的代码.

编辑4:我已经尝试了文档中的代码,发现值$SESSION_XML应该是

$SESSION_XML = '<iq type="set" id="4">'.
  '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>';
Run Code Online (Sandbox Code Playgroud)

完成转换后,我将发布C#代码.

Ale*_*ode 13

要使用X-FACEBOOK-PLATFORM,您将需要随传统身份验证流程提供的用户会话.但是,access_token包含|之后的用户会话 正如你在edit1中提到的那样.

我们在上一篇博文中宣布access_token将被加密,这将是从10月1日开始强制执行的.在此之前,该选项可以在高级应用程序设置http://developers.facebook.com/blog/post/553/中切换.

展望未来,access_token将能够用于X-FACEBOOK-PLATFORM.


Joe*_*and 7

如果从现有的XMPP库开始,您将获得更快的速度.这是一个列表:http://xmpp.org/xmpp-software/libraries/

例如,你会希望你没有手工编写所有的XML,而不是运行它通过DOM的非常快.在此期间,使用以下字符测试所有输入:<>'"&


Igy*_*Igy 5

在Facebook开发人员网站上有一个Python的例子可能有用:https: //developers.facebook.com/docs/chat/