Facebook:获取会话密钥时获取不正确的签名 (104)
Posted
技术标签:
【中文标题】Facebook:获取会话密钥时获取不正确的签名 (104)【英文标题】:Facebook: Getting Incorrect Signature (104) when Getting Session Key 【发布时间】:2010-11-27 09:50:30 【问题描述】:我正在尝试使用HttpClient 库(以调用 Facebook API 的 REST 端点)来获取会话密钥并验证用户...
我的代码在这里:
RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =
"classpath*:**/*applicationContext-test.xml" )
public class FacebookUserTest
final String API_KEY = "9e2568d68f182a2957878f3acedd9453";
final String SECRET = "f1298956895d39110be92a672e0d2284";
final String TOKEN = "aa0c41aa4532053e8d0097844ab9bc7d";
final String LOGIN = "http://www.facebook.com/login.php";
final String HOST = "http://www.facebook.com/restserver.php";
private static Logger log =
LoggerFactory.getLogger(FacebookUserTest.class);
protected FacebookUser FacebookUser;
@Test
public void testFindUserBySessionKey() throws Exception
loginToFacebook();
String sessionKey = getSessionKey();
public void loginToFacebook() throws Exception
HttpClient client = new HttpClient();
client.setParams(new HttpClientParams());
client.setState(new HttpState());
GetMethod get = new GetMethod(LOGIN + "?api_key=" + API_KEY
+ "&v=1.0&auth_token=" + TOKEN);
// Get login screen
client.executeMethod(get);
// Post credentials to login
PostMethod post = new PostMethod(LOGIN);
post.addParameter(new NameValuePair("api_key", API_KEY));
post.addParameter(new NameValuePair("v", "1.0"));
post.addParameter(new NameValuePair("auth_token", TOKEN));
post.addParameter(new NameValuePair("email", "user@email.com"));
post.addParameter(new NameValuePair("pass", "password"));
client.executeMethod(post);
public String getSessionKey() throws Exception
HttpClient client = new HttpClient();
// Obtain session key
String host = "http://www.facebook.com/restserver.php";
String sessSecret = "false";
String toMd = "api_key=" + API_KEY + "auth_token=" + TOKEN
+ "format=xmlgenerate_session_secret=" + sessSecret
+ "method=facebook.auth.getSessionv=1.0" + SECRET;
String md5 = Md5Utils.MD5(toMd);
PostMethod post = new PostMethod(HOST);
NameValuePair[] data =
new NameValuePair("api_key", API_KEY),
new NameValuePair("auth_token", TOKEN),
new NameValuePair("format", "xml"),
new NameValuePair("generate_session_secret", SECRET),
new NameValuePair("method", "auth.getSession"),
new NameValuePair("sig", md5), new NameValuePair("v", "1.0")
;
post.setRequestBody(data);
post.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
post.setRequestHeader("User-Agent",
"Facebook API PHP5 Client 1.1 (curl) 5");
// execute method and handle any error responses.
client.executeMethod(post);
StringBuilder sb = new StringBuilder();
byte[] b = new byte[4096];
for (int n; (n = post.getResponseBodyAsStream().read(b)) != -1;)
sb.append(new String(b, 0, n));
String sessionId = sb.toString();
log.warn("Session Id: " + sessionId);
return sessionId;
当我运行 JUnit 测试时,这是从控制台打印的内容:
WARN : com.myapp.FacebookUserTest - Session Id:
<?xml version="1.0" encoding="UTF-8"?>
<error_response xmlns="http://api.facebook.com/1.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://api.facebook.com/1.0/
http://api.facebook.com/1.0/facebook.xsd">
<error_code>104</error_code>
<error_msg>Incorrect signature</error_msg>
<request_args list="true">
<arg>
<key>api_key</key>
<value>9e2568d68f182a2957878f3acedd9453</value>
</arg>
<arg>
<key>auth_token</key>
<value>aa0c41aa4532053e8d0097844ab9bc7d</value>
</arg>
<arg>
<key>format</key>
<value>xml</value>
</arg>
<arg>
<key>generate_session_secret</key>
<value>f1298956895d39110be92a672e0d2284</value>
</arg>
<arg>
<key>method</key>
<value>auth.getSession</value>
</arg>
<arg>
<key>sig</key>
<value>fcf80d658f35d66396ac521da7102782</value>
</arg>
<arg>
<key>v</key>
<value>1.0</value>
</arg>
</request_args>
</error_response>
可能是我的 MD5Utils 代码:
public class Md5Utils
private static String convertToHex(byte[] data)
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++)
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
while (two_halfs++ < 1);
return buf.toString();
public static String MD5(String text)
throws NoSuchAlgorithmException, UnsupportedEncodingException
MessageDigest md;
md = MessageDigest.getInstance("MD5");
byte[] md5hash = new byte[32];
md.update(text.getBytes("iso-8859-1"), 0, text.length());
md5hash = md.digest();
return convertToHex(md5hash);
我可能做错了什么来生成不正确的签名?
如果有人可以帮助我或指出我正确的方向,我将不胜感激......
编程愉快,感谢阅读!
【问题讨论】:
【参考方案1】:试试这个
string GenerateSignature(IDictionary<string, string> parameters)
StringBuilder signatureBuilder = new StringBuilder();
// Sort the keys of the method call in alphabetical order
List<string> keyList = ParameterDictionaryToList(parameters);
keyList.Sort();
// Append all the parameters to the signature input paramaters
foreach (string key in keyList)
signatureBuilder.Append(String.Format(CultureInfo.InvariantCulture, "0=1", key, parameters[key]));
// Append the secret to the signature builder
signatureBuilder.Append(ConfigurationManager.AppSettings["FBApiSecret"]);
MD5 md5 = MD5.Create();
// Compute the MD5 hash of the signature builder
byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(signatureBuilder.ToString().Trim()));
// Reinitialize the signature builder to store the actual signature
signatureBuilder = new StringBuilder();
// Append the hash to the signature
foreach (byte hashByte in hash)
signatureBuilder.Append(hashByte.ToString("x2", CultureInfo.InvariantCulture));
return signatureBuilder.ToString();
string CreateHTTPParameterList(IDictionary<string, string> parameterList)
StringBuilder queryBuilder = new StringBuilder();
parameterList.Add("api_key", ConfigurationManager.AppSettings["FBApiKey"]);
parameterList.Add("v", "1.0");
parameterList.Add("call_id", DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture));
parameterList.Add("sig", GenerateSignature(parameterList));
//parameterList.Add("sig", _sig);
// Build the query
foreach (KeyValuePair<string, string> kvp in parameterList)
queryBuilder.Append(kvp.Key);
queryBuilder.Append("=");
queryBuilder.Append(HttpUtility.UrlEncode(kvp.Value));
queryBuilder.Append("&");
queryBuilder.Remove(queryBuilder.Length - 1, 1);
return queryBuilder.ToString();
示例用法:
Dictionary<string, string> parameterList = new Dictionary<string, string>();
parameterList.Add("auth_token", authCode);
parameterList.Add("format", "json");
parameterList.Add("method", "facebook.auth.getSession");
string req = CreateHTTPParameterList(parameterList);
我尝试从我的旧项目中复制/粘贴这些代码。 我希望它会对你有所帮助。
【讨论】:
【参考方案2】:您在 generate_session_secret 您的密码中发送的参数有错误,它必须是真或假
你设置: 新 NameValuePair("generate_session_secret", SECRET),
您在帖子中设置的参数与签名存在冲突
【讨论】:
以上是关于Facebook:获取会话密钥时获取不正确的签名 (104)的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 上获取 FB Chat 的 API 密钥和会话密钥和会话密钥