整合Facebook聊天 [英] Integrating Facebook chat

查看:173
本文介绍了整合Facebook聊天的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个程序来集成Facebook用户聊天在C#中,但是我总是得到< failure xmlns =urn:ietf:params:xml:ns:xmpp-sasl><在向服务器发送响应后,未授权/>< / 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); //发送初始请求
mySw.Flush();

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

//从服务器读取响应以查看支持的身份验证方法
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'+
FACEBOOK-PLATFORM'/>;

mySw.WriteLine(xml);
mySw.Flush(); //发送响应到服务器使用X-FACEBOOK-PLATFORM


//读取服务器发送的挑战
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>,);

//将挑战字符串转换为正常字符串
byte [] myregularstrigbytes = Convert.FromBase64String(myResponseAsSB.ToString());
string myregularstring = System.Text.Encoding.UTF8.GetString(myregularstrigbytes);


//我在这里修改了accesstoken这里的测试目的。
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(); //使用我的参数将响应发送到服务器

myResponseAsSB.Clear();

//检查身份验证是否成功
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());

}

私有字符串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 =+方法
+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)=>当前+ b.ToString(x2));

返回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);

}

我已经评价过这篇文章 C#中的Facebook聊天认证 X-FACEBOOK-PLATFORM ,我的应用程序类型是Native / Desktop。



有些可以指出我在右边方向?



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



编辑1:根据这个 SO答案访问令牌包含第一个|人物,我可以找到|字符到2天前,但现在我找不到|在访问令牌中的字符,它真的很奇怪,那么现在怎么找到会话密钥? (或者现在我可以睡觉了)。



编辑2:奇怪的是,我总是以< appId> |< sessionKey> |< digest> 用于本机/桌面应用程序。我进一步搜索,发现会话密钥需要从 auth中提取.promoteSession 旧版API,并使用 HttpUtility.UrlEncode 而不是 HttpUtility.HtmlEncode 对参数进行编码。



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



编辑3: strong>我已经在一个星期内撞了过头,但仍然没有起作用,但是今天我发现在文档请注意,这需要通过TLS(传输层安全性),否则您将收到错误。我想我需要修改我的代码。



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

  $ SESSION_XML ='< iq type =setid = 4 >。 
'< session xmlns =urn:ietf:params:xml:ns:xmpp-session/>< / iq>';

一旦完成转换,我将发布C#代码。

解决方案

要使用X-FACEBOOK-PLATFORM,您需要提供传统认证流程的用户会话。
但是,access_token包含在|之后的用户会话正如你在edit1中指出的那样。



我们在最后一篇博文中宣布access_token将被加密,这将是Octber 1st强制的。在此之前,该选项可以在高级应用程序设置中切换 http://developers.facebook.com/blog/post/ 553 /



未来,access_token将能够用于X-FACEBOOK-PLATFORM。


I have written a program to integrate Facebook user chat in C#, however I always get <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure> after sending the response to the server.

I've checked the API key and the App secret, both of them are correct. It looks like I'm passing some wrong parameters to the server.

Here is my code.

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);

    }

I've refereed to this articles Facebook Chat Authentication in C# and X-FACEBOOK-PLATFORM and my application type is of Native/Desktop.

Can some point me in the right direction?

Edit : I think the problem is while creating the signature, is there any way to verify the created signature?

Edit 1 : According to this SO answer the access token contains the session key after the first | character and I could find the | character till 2 days ago, but now I can't find the | character in the access token, its really strange, so how do I find the session key now? (Or may be I should go to sleep now.)

Edit 2 : Its strange that I always got the access token in form of <appId>|<sessionKey>|<digest> for native/desktop application. I did further searching and found out that the session key needs to be extracted from auth.promoteSession legacy api and encode the parameters using HttpUtility.UrlEncode instead of HttpUtility.HtmlEncode.

Now I've hard coded the Access token (verified it in the Access Token Debugger), the session key, App key and app secret still I get the same error <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>

Edit 3 : I have been banging my head over a week and still this doesn't work, but today I found a update in the documentation which says Note that this needs to be over TLS (Transport Layer Security) or you'll get an error. I guess I need to modify my code accordingly.

Edit 4 : I've tried out the code in the documentation and found that the value of $SESSION_XML should be

$SESSION_XML = '<iq type="set" id="4">'.
  '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>';

I will post the C# code once I finish converting it.

解决方案

To use X-FACEBOOK-PLATFORM you will need the user session which is provided with the legacy auth flow. However, the access_token contain the user session after the | as you noted in your edit1.

We announced in the last blog post that access_token will be encrypted and this will be mandatory from Octber 1st. Until then, the option can be toggle in the Advanced App settings http://developers.facebook.com/blog/post/553/.

Moving forward, access_token will be able to be use for X-FACEBOOK-PLATFORM.

这篇关于整合Facebook聊天的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆