使用Java解析Facebook签名的请求返回格式错误的JSON

使用Java解析Facebook签名的请求返回格式错误的JSON,java,json,facebook,Java,Json,Facebook,我试图在Javaservlet的doPost中解析Facebook签名的请求。我使用commons-codec-1.3的Base64对签名请求进行解码。 下面是我在servlet的doPost String signedRequest = (String) req.getParameter("signed_request"); String payload = signedRequest.split("[.]", 2)[1]; payload = payload.replace("-", "+"

我试图在Javaservlet的doPost中解析Facebook签名的请求。我使用commons-codec-1.3的Base64对签名请求进行解码。 下面是我在servlet的
doPost

String signedRequest = (String) req.getParameter("signed_request");
String payload = signedRequest.split("[.]", 2)[1];
payload = payload.replace("-", "+").replace("_", "/").trim();
String jsonString = new String(Base64.decodeBase64(payload.getBytes()));
当我将System.out导出
jsonString
时,它的格式不正确。有时它会错过JSON的结尾 有时它会错过字符串末尾的
“}


如何从Facebook获得正确的JSON响应?

我从未在Java中这样做过,因此我没有完整的答案,但事实上,字符串结尾有时会丢失一个字符,有时会丢失两个字符,这表明Base64填充可能有问题。您可能希望输出有效负载的值,看看它何时结束第i个“=”表示jsonString缺少“}”,当有效负载以“=”结尾时,表示jsonString缺少“}”。如果情况似乎是这样,那么有效载荷末尾的等号的解释就出了问题,这些等号应该代表空位


编辑:进一步思考,我认为这是因为Facebook使用Base64 URL编码(不添加=作为pad字符),而不是常规的Base64,然而,您的解码函数需要常规的Base64,尾随=chars。

我已经升级到common-codec-1.5,使用的代码与此非常相似,我没有遇到此问题。您是否确认使用在线解码器确实会导致有效负载格式错误?

facebook正在使用Base64作为URL,您可能正在尝试使用标准Base64算法对文本进行解码。 除此之外,URL变量不需要用“=”填充

  • 您可以在代码中添加所需的字符(填充等)
  • 您可以使用commons编解码器1.5(new Base64(true)),其中添加了对这种编码的支持

  • Facebook正在向您发送“未添加的”Base64值(URL“标准”),这对于Java解码器来说是一个问题,因为他们并不期望这样做。当要解码的Base64编码数据的长度不是4的倍数时,您可以判断出问题

    我使用此函数来修复值:

    public static String padBase64(String b64) {
        String padding = "";
        // If you are a java developer, *this* is the critical bit.. FB expects
        // the base64 decode to do this padding for you (as the PHP one
        // apparently
        // does...
        switch (b64.length() % 4) {
        case 0:
            break;
        case 1:
            padding = "===";
            break;
        case 2:
            padding = "==";
            break;
        default:
            padding = "=";
        }
        return b64 + padding;
    
    }
    

    当我打印签名的_请求时,它不会在有效负载的末尾显示任何=或=。这是否意味着我收到了错误的签名请求。是否有可能因为我在Facebook应用程序设置过程中给出的url而出错。我认为您的Java函数希望输入中填充=chars,但Facebook没有使用它们。如果decodeBase64与字符串的行为不同,请尝试直接传递有效负载,而不是payload.getBytes()。然后尝试跳过替换调用,以防decodeBase64设置为基于-uu或+/chars的存在自动检测编码。如果所有操作都失败,则必须找到另一个能够理解Base64 URL变量的方法,或者篡改输入或输出以解决不匹配问题(这应该是可行的,因为它只会影响最后1-2个字符)。也请查看我。非常感谢。在这里查看有关Apache Commons编解码器的更多详细信息