<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);
}
我参考了这篇文章 Facebook Chat Authentication in C# 和 X-FACEBOOK-PLATFORM,我的应用程序类型是Native/Desktop。有人能指点我正确的方向吗?
编辑:我认为问题出在创建签名时,是否有一种方法来验证创建的签名?
编辑1:根据这个SO答案,第一个|字符后访问令牌包含会话密钥,我可以找到|字符直到2天前,但现在我找不到|字符在访问令牌中,这真的很奇怪,那么我现在该如何找到会话密钥呢?(或许我应该去睡觉了。)
编辑2:奇怪的是,我总是以
<appId>|<sessionKey>|<digest>
形式获得本机/桌面应用程序的访问令牌。我进一步搜索并发现需要从auth.promoteSession遗留API中提取会话密钥,并使用HttpUtility.UrlEncode
而不是HttpUtility.HtmlEncode
对参数进行编码。现在,我已经硬编码了访问令牌(在访问令牌调试器中进行了验证),会话密钥,App密钥和应用程序密码仍然出现相同的错误
<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>
编辑3:我已经苦思冥想了一个星期,但这仍然没有作用,但今天我在文档中发现了一个更新,其中说请注意,这需要通过TLS(传输层安全性)进行,否则将会产生错误。
我想我需要相应地修改我的代码。编辑4:我尝试了文档中的代码,并发现
$SESSION_XML
的值应该是:$SESSION_XML = '<iq type="set" id="4">'.
'<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>';
我完成转换后会发布C#代码。
xmpp_login
扩展权限? - Casey ChuHtmlEncode
调用会发生什么?您哈希的参数应该与您传递的参数完全相同。另外,如果您不包括call_id
参数会发生什么?一年前我写类似的代码时没有包括那个参数。 - Casey Chu