0

我们有一个带有 spring mvc 控制器的 spring web 应用程序。它应该连接到我们的 facebook 应用程序以获取用于进一步访问的身份验证令牌。与我们的应用程序的通信似乎有效。当我点击链接

<a href="https://www.facebook.com/dialog/oauth?client_id=something&redirect_uri=http://our.domaine.register/postback?user_id=12345&scope=manage_pages&response_type=code">connect</a>

它会将我重定向到 facebook,我将输入我的凭据并重定向回

our.domaine.register/postback?user_id=12345&code=SoMEcOde

这又是我们的 Spring MVC 控制器之一,但这并不重要,因为

问题是,facebook 返回的代码是格式错误的 accessToken

这意味着如果我尝试使用它来访问受保护的资源,它将无法工作。用通过图形 API 资源管理器检索到的访问令牌替换相同的调用,它工作正常。

返回的代码具有特殊的格式,其中包含“-”、“_”和“=”字符,这是普通访问令牌所没有的。

所以我假设必须进行某种转换?!还是某种格式问题?

返回的令牌:

AQBoXkcR5zRUiuHoO_lLdQfnxxxxxxxxxxxxxxxxoPPvZQTeybT9ebsI2SD1Xk

代码和accessToken一样吗?

官方文档大多只是谈论使用锚散列(REDIRECT_URL/#access_token=...)和通过javascript访问access_token,虽然我不知道为什么我要这样做,它不自然也不可测试......

有没有人使用 code 参数将其映射为请求参数,以便可以在控制器中访问它?

4

2 回答 2

2

看起来您的 response_type 正在请求代码,这就是没有返回令牌的原因。

请检查https://developers.facebook.com/docs/authentication/的最后一部分

正确呼叫的示例;

https://www.facebook.com/dialog/oauth?
    client_id=YOUR_APP_ID
   &redirect_uri=https://www.facebook.com/connect/login_success.html
   &response_type=token

当登录成功时,重定向 ur 包含附加的 access_token 和 expires_in 参数。您可以解码 url 参数以获得所需的内容。这是Android OAuth 示例的示例函数(易于适应 java):

public static Bundle decodeUrl(String s) {
        Bundle params = new Bundle();
        if (s != null) {
            String array[] = s.split("&");
            for (String parameter : array) {
                String v[] = parameter.split("=");
                // YG: in case param has no value
                if (v.length==2){
                    params.putString(URLDecoder.decode(v[0]),
                                 URLDecoder.decode(v[1]));
                }
                else {
                    params.putString(URLDecoder.decode(v[0])," ");
                }
            }
        }
        return params;
    }

    /**
     * Parse a URL query and fragment parameters into a key-value bundle.
     * 
     * @param url the URL to parse
     * @return a dictionary bundle of keys and values
     */
    public static Bundle parseUrl(String url) {

        try {
            URL u = new URL(url);
            Bundle b = decodeUrl(u.getQuery());
            b.putAll(decodeUrl(u.getRef()));
            return b;
        } catch (MalformedURLException e) {
            Log.w(TAG, "parseUrl ex ->" + e.toString());
            return new Bundle();
        }
    }
于 2012-07-31T16:40:19.217 回答
1

他们返回给您的代码是 OAuth 授权代码,没有访问令牌。您必须用另一个呼叫交换那个访问令牌。有关服务器端身份验证,请参阅 Facebook 文档中的第 4 点

更新:( 对不起,错过了标题,你说“客户端身份验证”;))

使用response_type=token代替response_type=code,因此您可以直接获得访问令牌而不是 OAuth 授权码。请参阅Facebook 的客户端身份验证文档中不使用 JS SDK的客户端身份验证部分

更新:

当您尝试开发 Web 应用程序时,使用服务器端身份验证流程是正确的。这意味着将授权码(重定向用户后获得的授权码)换成另一个调用的访问令牌。

因此,如果我现在理解正确,那么您的问题是如何从收到的响应中获取访问令牌。查看此示例以了解如何使用 Spring 执行此类操作。对于您的情况,这类似于获取授权码:

@RequestMapping(value = "/postback", params = "code", method = RequestMethod.GET)
@ResponseBody
private void accessCode(@RequestParam("code") String code,
                            HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
        //Now the variable 'code' holds the authorization code
}
于 2012-07-31T16:38:11.577 回答