Facebook:获取会话密钥时签名不正确 (104)

发布于 2024-08-04 15:22:57 字数 6301 浏览 5 评论 0原文

我正在尝试使用 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", "[email protected]"));
        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);
   }
}

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

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

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

I am trying to use the HttpClient library (in order to call the Facebook API's REST end points) to obtain a session key and verify user...

My code is here:

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", "[email protected]"));
        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;
     }
}

When I run my JUnit test, this is what is printed from the console:

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>

Could it be my MD5Utils code:

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

What am I possibly doing wrong to generate an incorrect signature?

Would really appreciate it if someone could help me or point me in the right direction...

Happy programming and thanks for reading!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

人海汹涌 2024-08-11 15:22:57

尝试这个

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

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

Try this

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

Example usage :

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

I tryed to copy / paste these codes from my old project.
I hope it will be help to you.

美羊羊 2024-08-11 15:22:57

您在generate_session_secret中发送的参数有错误您的密码,

您设置的必须是true或false:
new NameValuePair("generate_session_secret", SECRET),

您在帖子中设置的参数和签名存在冲突

you have an error in your parameter you send in generate_session_secret your secret code , it must be true or false

you set:
new NameValuePair("generate_session_secret", SECRET),

there are conflict in your parameter that u set in post and the signature

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文