16

FacebookユーザーチャットをC#に統合するプログラムを作成しました<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>が、サーバーに応答を送信した後に必ず取得します。

APIキーとアプリシークレットを確認しましたが、どちらも正しいです。サーバーに間違ったパラメーターを渡しているようです。

これが私のコードです。

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

    }

この記事を参照しました。C#およびX-FACEBOOK-PLATFORMでのFacebookチャット認証で、アプリケーションの種類はネイティブ/デスクトップです。

誰かが私を正しい方向に向けることができますか?

編集: 問題は署名の作成中にあると思いますが、作成された署名を確認する方法はありますか?

編集1:このSO回答によると、アクセストークンには最初の|の後にセッションキーが含まれています キャラクターと私は|を見つけることができました 2日前まではキャラクターでしたが、今は見つかりません| アクセストークンの文字、それは本当に奇妙です、それで私は今セッションキーをどのように見つけるのですか?(または、私は今寝るべきかもしれません。)

編集2:<appId>|<sessionKey>|<digest>私が常にネイティブ/デスクトップアプリケーションの形式でアクセストークンを取得したのは奇妙です。さらに検索したところ、セッションキーをauth.promoteSessionレガシーAPIから抽出し、のHttpUtility.UrlEncode代わりにを使用してパラメーターをエンコードする必要があることがわかりましたHttpUtility.HtmlEncode

これで、アクセストークン(アクセストークンデバッガーで確認済み)、セッションキー、アプリキー、アプリシークレットをハードコーディングしましたが、同じエラーが発生します<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>

編集3:私は1週間以上頭を叩いてきましたが、それでもこれは機能しませんが、今日、ドキュメントに更新があり、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>';

変換が完了したら、C#コードを投稿します。

4

5 に答える 5

13

X-FACEBOOK-PLATFORMを使用するには、従来の認証フローで提供されるユーザーセッションが必要です。ただし、access_tokenには、|の後にユーザーセッションが含まれています。edit1で述べたように。

前回のブログ投稿で、access_tokenは暗号化され、10月1日から必須になると発表しました。それまでは、アプリの詳細設定http://developers.facebook.com/blog/post/553/でオプションを切り替えることができます。

今後、access_tokenはX-FACEBOOK-PLATFORMで使用できるようになります。

于 2011-09-06T18:11:49.673 に答える
7

既存のXMPPライブラリから始めると、さらに速くなります。リストは次のとおりです:http://xmpp.org/xmpp-software/libraries/

たとえば、すぐにDOMを実行するのではなく、すべてのXMLを手動でコーディングしていなかったらいいのにと思うでしょ。それまでの間、次の文字を使用してすべての入力をテストしてください。<>'"&

于 2011-08-29T08:08:02.393 に答える
5

Facebook DeveloperサイトにPythonの例があります: https ://developers.facebook.com/docs/chat/

于 2011-08-29T06:12:06.890 に答える
1

X-FACEBOOK-PLATFORMを使用して認証を試みる前に、同じ問題が発生しました。私はあなたを助けることができると思う解決策を見つけました。

X-FACEBOOK-PLATFORMをサポートするJavaAsmackライブラリを備えたXMPP

コードはJavaですが、どのように機能するかを理解するのは簡単です。秘訣は、OAuth2.0トークンを使用してFacebookからセッション秘密鍵を取得することです。次のように、auth.promoteSessionと呼ばれる非推奨のメソッドを使用する必要があります。

https://api.facebook.com/method/auth.promoteSession?access_token=yourAccessToken

次に、Facebookは、アプリケーションの秘密鍵パラメーターとして使用する必要があるセッション秘密鍵を提供します。このメソッドを使用できるようにするには、このページの[設定の編集]セクションと[詳細設定]タブで[非推奨のAPIの削除]パラメーターを無効にする必要があります。

これがお役に立てば幸いです。

于 2011-09-10T03:56:41.083 に答える
1

これが問題であるかどうかはわかりません。テストする時間がありませんが、あなたの署名は私には間違っているように見えます。また、Facebookは9月の初めにOAuth 2.0に移行したことを忘れないでください。したがって、access_tokenが正しいことを確認してください。

これを試して:

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

MD5 md = MD5.Create();
var hash = md.ComputeHash(Encoding.UTF8.GetBytes(sig));
sig = hash.Aggregate("", (current, b) => current + b.ToString("x2"));

var response = "api_key=" + appId
     + "&call_id=" + callId
     + "&method=" + method
     + "&nonce=" + nonce
     + "&session_key=" + SessionKey
     + "&v=1.0";

 // response & signature
 response = string.Concat(Uri.EscapeDataString(response),
                         "&", Uri.EscapeDataString(sig))

 // base64 encode
 var myEncodedResponseToSend = Convert.ToBase64String(
                                        ASCIIEncoding.ASCII.GetBytes(response));
于 2011-09-10T21:07:54.467 に答える