java - Facebook:获取 session key 时签名不正确 (104)

标签 java facebook rest junit httpclient

我正在尝试使用 HttpClient库(为了调用 Facebook API 的 REST 端点)来获取 session key 并验证用户...

我的代码在这里:

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

我可能做错了什么来生成不正确的签名?

如果有人可以帮助我或为我指明正确的方向,我将非常感激......

祝您编程愉快,感谢您的阅读!

最佳答案

试试这个

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

我尝试从我的旧项目中复制/粘贴这些代码。 希望对您有所帮助。

关于java - Facebook:获取 session key 时签名不正确 (104),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1409220/

相关文章:

rest - Swagger/RAML(或任何类似的 REST API 规范)是否支持 REST 异步客户端回调?

java - 如何在 recyclerView 的适配器中调用 scrollToPosition(position)?

java - 更改时间显示的格式

java - 如果ID是IDENTITY COLUMN,如何删除或更改ID?

iphone - 在我的iPhone应用程序中集成Facebook发布请求

php - 在 PHP 中创建 RESTful API?

php - 如何重新定义Slim v3的错误处理程序?

java - 如何使用 JSF 获取用户的浏览器 ID?

Facebook JavaScript SDK : Publish actions with custom Open Graph objects

facebook - 如何跟踪 Facebook iframe 应用程序的流量来源