使用 OAUTH 2.0 验证并从 Facebook cookie 获取数据

发布于 2024-12-05 21:28:48 字数 329 浏览 0 评论 0原文

我有一个用 GWT 制作的网页。在那里,我使用所有登录 facebook 的东西和一个受操纵的 gwtfb 库,一切正常。迁移到 oauth 2.0 后,发送到服务器的 cookie 已更改为加密的 cookie。

我想要一个 java 示例代码,它在服务器中实现与旧代码相同:

  • 我需要像使用 cookie md5 技巧之前那样验证调用,以了解是否已进行调用通过我的客户页面。
  • 从该 cookie 获取数据:我需要 Facebook 用户。

如果可能的话不调用FB,只使用cookie数据。

提前致谢。

I have a web page made in GWT. There I use all the login facebook stuff with a manipulated gwtfb library, all works fine. After migrating to oauth 2.0 now the cookie sent to the server has changed to a encrypted one.

I want to get a java example code that implements in the server the same than the old one:

  • I need to validate the call like I did before using the cookie md5 trick to know if the call has been made by my client page.
  • Get data from that cookie: I need the facebook user.

If possible not calling FB, just using the cookie data.

Thanks in advance.

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

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

发布评论

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

评论(3

嗫嚅 2024-12-12 21:28:49

好吧,虽然我有一些很好的答案,但我还是用我在博客中写的内容来回答自己:
http://pablocastilla.wordpress.com/2011 /09/25/how-to-implement-oauth-f/

现在cookie发生了很大变化:它是加密的,没有accesstoken及其内容格式改变了很多。这里有一些讨论它的链接:

http://developers.facebook.com/docs /authentication/signed_request/

http://developers.facebook.com/docs/authentication/

http://blog.sociablelabs.com/2011/09/19/server-side-changes-facebook-oauth-2-0-upgrade/

因此,要验证 cookie,请从中获取用户并获取您可以使用以下代码的访问令牌:

public class FaceBookSecurity {

// return the fb user in the cookie.
public static String getFBUserFromCookie(HttpServletRequest request)
        throws Exception {
    Cookie fbCookie = getFBCookie(request);

    if (fbCookie == null)
        return null;

    // gets cookie value
    String fbCookieValue = fbCookie.getValue();

    // splits it.
    String[] stringArgs = fbCookieValue.split("\\.");
    String encodedPayload = stringArgs[1];

    String payload = base64UrlDecode(encodedPayload);

    // gets the js object from the cookie
    JsonObject data = new JsonObject(payload);

    return data.getString("user_id");

}

public static boolean ValidateFBCookie(HttpServletRequest request)
        throws Exception {

    Cookie fbCookie = getFBCookie(request);

    if (fbCookie == null)
        throw new NotLoggedInFacebookException();

    // gets cookie information
    String fbCookieValue = fbCookie.getValue();

    String[] stringArgs = fbCookieValue.split("\\.");
    String encodedSignature = stringArgs[0];
    String encodedPayload = stringArgs[1];

    //decode
    String sig = base64UrlDecode(encodedSignature);
    String payload = base64UrlDecode(encodedPayload);

    // gets the js object from the cookie
    JsonObject data = new JsonObject(payload);

    if (!data.getString("algorithm").Equals("HMAC-SHA256")) {
        return false;
    }

    SecretKey key = new SecretKeySpec(
            ApplicationServerConstants.FacebookSecretKey.getBytes(),
            "hmacSHA256");

    Mac hmacSha256 = Mac.getInstance("hmacSHA256");
    hmacSha256.init(key);
    // decode the info.
    byte[] mac = hmacSha256.doFinal(encodedPayload.getBytes());

    String expectedSig = new String(mac);

    // compare if the spected sig is the same than in the cookie.
    return expectedSig.equals(sig);

}

public static String getFBAccessToken(HttpServletRequest request)
        throws Exception {
    Cookie fbCookie = getFBCookie(request);

    String fbCookieValue = fbCookie.getValue();

    String[] stringArgs = fbCookieValue.split("\\.");
    String encodedPayload = stringArgs[1];

    String payload = base64UrlDecode(encodedPayload);

    // gets the js object from the cookie
    JsonObject data = new JsonObject(payload);

    String authUrl = getAuthURL(data.getString("code"));
    URL url = new URL(authUrl);
    URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(),
            url.getQuery(), null);
    String result = readURL(uri.toURL());

    String[] resultSplited = result.split("&");

    return resultSplited[0].split("=")[1];

}

// creates the url for calling to oauth.
public static String getAuthURL(String authCode) {
    String url = "https://graph.facebook.com/oauth/access_token?client_id="
            + ApplicationConstants.FacebookApiKey
            + "&redirect_uri=&client_secret="
            + ApplicationServerConstants.FacebookSecretKey + "&code="
            + authCode;

    return url;
}

// reads the url.
private static String readURL(URL url) throws IOException {

    InputStream is = url.openStream();

    InputStreamReader inStreamReader = new InputStreamReader(is);
    BufferedReader reader = new BufferedReader(inStreamReader);

    String s = "";

    int r;
    while ((r = is.read()) != -1) {
        s = reader.readLine();
    }

    reader.close();
    return s;
}

private static String base64UrlDecode(String input) {
    String result = null;
    Base64 decoder = new Base64(true);
    byte[] decodedBytes = decoder.decode(input);
    result = new String(decodedBytes);
    return result;
}

    private static Cookie getFBCookie(HttpServletRequest request) 
    {
        Cookie[] cookies = request.getCookies();

        if (cookies == null)
            return null;

        Cookie fbCookie = null;

        for (Cookie c : cookies) {
            if (c.getName().equals(
                "fbsr_" + ApplicationServerConstants.FacebookApiKey)) {
                fbCookie = c;
            }
        }
        return fbCookie;
    }
}

Well, although I have a few good answers I answer myself with what I have written in my blog:
http://pablocastilla.wordpress.com/2011/09/25/how-to-implement-oauth-f/

Now the cookie has changed a lot: it is encrypted, doesn't have the accesstoken and its content format has changed a lot. Here you have a few links talking about it:

http://developers.facebook.com/docs/authentication/signed_request/

http://developers.facebook.com/docs/authentication/

http://blog.sociablelabs.com/2011/09/19/server-side-changes-facebook-oauth-2-0-upgrade/

So to validate the cookie, get the user from it and get the access token you could use this code:

public class FaceBookSecurity {

// return the fb user in the cookie.
public static String getFBUserFromCookie(HttpServletRequest request)
        throws Exception {
    Cookie fbCookie = getFBCookie(request);

    if (fbCookie == null)
        return null;

    // gets cookie value
    String fbCookieValue = fbCookie.getValue();

    // splits it.
    String[] stringArgs = fbCookieValue.split("\\.");
    String encodedPayload = stringArgs[1];

    String payload = base64UrlDecode(encodedPayload);

    // gets the js object from the cookie
    JsonObject data = new JsonObject(payload);

    return data.getString("user_id");

}

public static boolean ValidateFBCookie(HttpServletRequest request)
        throws Exception {

    Cookie fbCookie = getFBCookie(request);

    if (fbCookie == null)
        throw new NotLoggedInFacebookException();

    // gets cookie information
    String fbCookieValue = fbCookie.getValue();

    String[] stringArgs = fbCookieValue.split("\\.");
    String encodedSignature = stringArgs[0];
    String encodedPayload = stringArgs[1];

    //decode
    String sig = base64UrlDecode(encodedSignature);
    String payload = base64UrlDecode(encodedPayload);

    // gets the js object from the cookie
    JsonObject data = new JsonObject(payload);

    if (!data.getString("algorithm").Equals("HMAC-SHA256")) {
        return false;
    }

    SecretKey key = new SecretKeySpec(
            ApplicationServerConstants.FacebookSecretKey.getBytes(),
            "hmacSHA256");

    Mac hmacSha256 = Mac.getInstance("hmacSHA256");
    hmacSha256.init(key);
    // decode the info.
    byte[] mac = hmacSha256.doFinal(encodedPayload.getBytes());

    String expectedSig = new String(mac);

    // compare if the spected sig is the same than in the cookie.
    return expectedSig.equals(sig);

}

public static String getFBAccessToken(HttpServletRequest request)
        throws Exception {
    Cookie fbCookie = getFBCookie(request);

    String fbCookieValue = fbCookie.getValue();

    String[] stringArgs = fbCookieValue.split("\\.");
    String encodedPayload = stringArgs[1];

    String payload = base64UrlDecode(encodedPayload);

    // gets the js object from the cookie
    JsonObject data = new JsonObject(payload);

    String authUrl = getAuthURL(data.getString("code"));
    URL url = new URL(authUrl);
    URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(),
            url.getQuery(), null);
    String result = readURL(uri.toURL());

    String[] resultSplited = result.split("&");

    return resultSplited[0].split("=")[1];

}

// creates the url for calling to oauth.
public static String getAuthURL(String authCode) {
    String url = "https://graph.facebook.com/oauth/access_token?client_id="
            + ApplicationConstants.FacebookApiKey
            + "&redirect_uri=&client_secret="
            + ApplicationServerConstants.FacebookSecretKey + "&code="
            + authCode;

    return url;
}

// reads the url.
private static String readURL(URL url) throws IOException {

    InputStream is = url.openStream();

    InputStreamReader inStreamReader = new InputStreamReader(is);
    BufferedReader reader = new BufferedReader(inStreamReader);

    String s = "";

    int r;
    while ((r = is.read()) != -1) {
        s = reader.readLine();
    }

    reader.close();
    return s;
}

private static String base64UrlDecode(String input) {
    String result = null;
    Base64 decoder = new Base64(true);
    byte[] decodedBytes = decoder.decode(input);
    result = new String(decodedBytes);
    return result;
}

    private static Cookie getFBCookie(HttpServletRequest request) 
    {
        Cookie[] cookies = request.getCookies();

        if (cookies == null)
            return null;

        Cookie fbCookie = null;

        for (Cookie c : cookies) {
            if (c.getName().equals(
                "fbsr_" + ApplicationServerConstants.FacebookApiKey)) {
                fbCookie = c;
            }
        }
        return fbCookie;
    }
}
海未深 2024-12-12 21:28:49

我刚刚将其添加到 BatchFB 的新版本 (2.1.1):http://code.google。 com/p/batchfb/

获取用户id:

FacebookCookie data = FacebookCookie.decode(cookie, YOURAPPSECRET);
System.out.println("Facebook user id is " + data.getFbId());

你可以在这里看到代码,它使用Jackson解析JSON并使用javax.crypto.Mac来验证签名:

http://code.google.com /p/batchfb/source/browse/trunk/src/com/googlecode/batchfb/FacebookCookie.java

不幸的是,获取访问令牌要复杂得多。 fbsr_ cookie 中的数据包含一个“代码”,您可以使用该代码进行图形 api 获取以获取真正的访问令牌...您必须将其存储在某个 cookie 或会话中。这太蹩脚了。

更好的解决方案是从 javascript 设置您自己的访问令牌 cookie。每次调用 FB.getLoginStatus() 时,请设置(或删除)您自己的 cookie。您无需担心访问令牌的签名,因为它是不可猜测的。

I just added this to a new release (2.1.1) of BatchFB: http://code.google.com/p/batchfb/

To get the user id:

FacebookCookie data = FacebookCookie.decode(cookie, YOURAPPSECRET);
System.out.println("Facebook user id is " + data.getFbId());

You can see the code here, which uses Jackson to parse the JSON and javax.crypto.Mac to verify the signature:

http://code.google.com/p/batchfb/source/browse/trunk/src/com/googlecode/batchfb/FacebookCookie.java

Unfortunately getting the access token is considerably more complicated. The data that comes in the fbsr_ cookie includes a "code" which you can then use to make a graph api fetch to get a real access token... which you would have to store in a cookie or session somewhere. This is incredibly lame.

An better solution is to set your own access token cookie from javascript. Every time you call FB.getLoginStatus(), have it set (or remove) your own cookie. You don't need to worry about signing the access token since it's unguessable.

醉生梦死 2024-12-12 21:28:49

我认为 cookie 数据是任意格式的 - 因为你不应该自己解释它? SDK 确实应该为您验证 cookie 吗?

I think the cookie data is in an arbitary format - because you shouldn't be interpreting it yourself? Surely the SDK should be validating the cookie for you?

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