如何使用 OAuth 使用 Facebook 帐户登录 Google App Engine 的 Java 示例

Posted

技术标签:

【中文标题】如何使用 OAuth 使用 Facebook 帐户登录 Google App Engine 的 Java 示例【英文标题】:Java example of how to log in to Google App Engine with a Facebook account using OAuth 【发布时间】:2012-03-22 22:40:47 【问题描述】:

我搜索了很多,阅读了很多博客、文章、教程,但直到现在还没有找到使用 Facebook 帐户登录我的应用程序的工作示例。

我知道我必须使用 OAuth、获取令牌、授权等...

谁能分享一个例子?

【问题讨论】:

【参考方案1】:

这是我在 App Engine 上的操作方式:

第 1 步)在 Facebook 上注册一个“应用程序”(参见https://developers.facebook.com/)。你给 Facebook 一个应用程序的名称和一个 URL。您注册的 url 是您要处理登录的页面(jsp 或 servlet)的 url。从注册中你会得到两个字符串,一个“app ID”和一个“app secret”(后者是你的密码,不要泄露或写在html中)。

对于这个例子,假设我注册的 url 是“http://myappengineappid.appspot.com/signin_fb.do”。

2) 从网页中,例如使用按钮,您将用户重定向到 Facebook 上的以下网址,在下面的示例中将您的应用程序 ID 替换为“myfacebookappid”。您还必须选择要询问用户的权限(或“范围”)(参见https://developers.facebook.com/docs/reference/api/permissions/)。在示例中,我只要求访问用户的电子邮件。

(要知道的一件有用的事情是,您还可以传递一个可选字符串,该字符串将在“state”参数中原封不动地返回。例如,我传递了用户的数据存储密钥,因此我可以在 Facebook 传递时检索用户把钥匙还给我。在这个例子中我没有这样做。)

这是一个jsp sn-p:

<%@page import="java.net.URLEncoder" %>
<%
    String fbURL = "http://www.facebook.com/dialog/oauth?client_id=myfacebookappid&redirect_uri=" + URLEncoder.encode("http://myappengineappid.appspot.com/signin_fb.do") + "&scope=email";
%>

<a href="<%= fbURL %>"><img src="/img/facebook.png" border="0" /></a>

3) 您的用户将被转发到 Facebook,并要求您批准您请求的权限。然后,用户将被重定向回您注册的 url。在本例中,这是“http://myappengineappid.appspot.com/signin_fb.do”,在我的 web.xml 中映射到以下 servlet:

import org.json.JSONObject;
import org.json.JSONException;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SignInFB extends HttpServlet 

    public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException             
        String code = req.getParameter("code");
        if (code == null || code.equals("")) 
            // an error occurred, handle this
        

        String token = null;
        try 
            String g = "https://graph.facebook.com/oauth/access_token?client_id=myfacebookappid&redirect_uri=" + URLEncoder.encode("http://myappengineappid.appspot.com/signin_fb.do", "UTF-8") + "&client_secret=myfacebookappsecret&code=" + code;
            URL u = new URL(g);
            URLConnection c = u.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
            String inputLine;
            StringBuffer b = new StringBuffer();
            while ((inputLine = in.readLine()) != null)
                b.append(inputLine + "\n");            
            in.close();
            token = b.toString();
            if (token.startsWith(""))
                throw new Exception("error on requesting token: " + token + " with code: " + code);
         catch (Exception e) 
                // an error occurred, handle this
        

        String graph = null;
        try 
            String g = "https://graph.facebook.com/me?" + token;
            URL u = new URL(g);
            URLConnection c = u.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
            String inputLine;
            StringBuffer b = new StringBuffer();
            while ((inputLine = in.readLine()) != null)
                b.append(inputLine + "\n");            
            in.close();
            graph = b.toString();
         catch (Exception e) 
                // an error occurred, handle this
        

        String facebookId;
        String firstName;
        String middleNames;
        String lastName;
        String email;
        Gender gender;
        try 
            JSONObject json = new JSONObject(graph);
            facebookId = json.getString("id");
            firstName = json.getString("first_name");
            if (json.has("middle_name"))
               middleNames = json.getString("middle_name");
            else
                middleNames = null;
            if (middleNames != null && middleNames.equals(""))
                middleNames = null;
            lastName = json.getString("last_name");
            email = json.getString("email");
            if (json.has("gender")) 
                String g = json.getString("gender");
                if (g.equalsIgnoreCase("female"))
                    gender = Gender.FEMALE;
                else if (g.equalsIgnoreCase("male"))
                    gender = Gender.MALE;
                else
                    gender = Gender.UNKNOWN;
             else 
                gender = Gender.UNKNOWN;
            
         catch (JSONException e) 
            // an error occurred, handle this
        

        ...

我已删除错误处理代码,因为您可能希望以与我不同的方式处理它。 (另外,“性别”当然是我定义的一个类。)此时,您可以将数据用于任何您想要的,例如注册新用户或寻找现有用户登录。注意“ myfacebookappsecret" 字符串当然应该是您从 Facebook 获取的应用程序密码。

您将需要“org.json”包来使用此代码,您可以在以下位置找到它:http://json.org/java/(只需获取 .java 文件并将它们添加到您的代码中的 org/json 文件夹结构中)。

我希望这会有所帮助。如果有什么不清楚的地方,请发表评论,我会更新答案。

前动画,-亚历山大。

****更新****

我想补充一些花絮,如果其中一些看起来有点过分,我深表歉意。

为了能够通过他/她的 Facebook 帐户登录用户,您需要知道我们正在谈论的数据存储区中的哪个用户。如果是新用户,很简单,创建一个新用户对象(使用名为“facebookId”的字段,或任何您想调用的字段,您从 Facebook 获得其值),将其保存在数据存储中并登录用户。

如果用户存在,您需要拥有带有 facebookId 的字段。当用户从 Facebook 重定向时,您可以获取 facebookId,并在数据存储中查找您要登录的用户。

如果您已经有用户,您需要让他们以您通常的方式登录,这样您就知道他们是谁,然后将他们发送到 Facebook,取回 facebookId 并更新他们的用户对象。这样,他们下次可以使用 Facebook 登录。

另一个小提示:用户将在 Facebook 上看到一个屏幕,要求您允许您的应用访问您要求的任何范围,这是无法解决的(您要求的范围越少,看起来越少的干扰,尽管)。但是,这只会在用户第一次被重定向时发生(除非您稍后要求更多范围,否则它会再次要求)。

【讨论】:

我没有看到您验证 signed_request 属性来验证用户/请求是否实际有效,但除此之外,这些确实是要采取的步骤...... Alexander,使用此代码,如果用户登录到 facebook,并打开我的 GAE,它会自动检查 facebook 帐户吗?或者用户总是需要点击某个地方来“验证”? 你可以用这段代码做两件事。 (1) 允许新用户点击“使用 facebook 注册”和 (2) 允许现有用户只需点击“使用您的 facebook 帐户登录”即可登录。他们都可以单击相同的链接,并且当上面的 servlet 运行时,您可以检查数据库并查看您是否有使用此 facebookId 的注册用户。如果是,您可以登录该用户。如果不是,您可以创建一个新用户,并存储 facebookId。是的,如果用户已登录 facebook 并已批准任何权限,则此代码将登录此人,而无需单击任何位置。 一个小的附加说明:您当然也可以允许您的应用程序的现有用户使用 Facebook 登录(即使用他们的 facebookId 更新他们的用户对象)。例如,这可以通过在我简要提到的状态参数中传递用户的数据存储密钥来完成,然后让上面的 servlet 抓取它并使用 facebookId 更新用户(或者您可以使用会话来检测用户)。跨度> Alexander,谢谢你的所有想法,今晚我会努力让它在我的 APP 上运行【参考方案2】:

你可以试试 face4j https://github.com/nischal/face4j/wiki 。我们已经在我们的产品http://grabinbox.com 上使用了它,并且开源了它供任何人使用。它在 GAE 上运行良好。

wiki 上有一个示例,可以帮助您在几分钟内将登录与 facebook 集成。

face4j 使用 oAuth 2.0 和 facebook graph API。

【讨论】:

@Jus12 它要求 face4j 而不是 twitter4j。所以我猜不会。【参考方案3】:

我在尝试自己实施 OAuth 签名时遇到了很多困难。我花了很多时间尝试调试我的令牌实际上没有获得授权的问题——显然这是一个常见问题。不幸的是,没有一个解决方案对我有用,所以我最终只使用了Scribe,这是一个漂亮的 Java OAuth 库,它具有支持除 Facebook 之外的其他提供商(例如 Google、Twitter 等)的额外好处

【讨论】:

【参考方案4】:

可以看一下LeanEngine,服务端部分:https://github.com/leanengine/LeanEngine-Server/tree/master/lean-server-lib/src/main/java/com/leanengine/server/auth

【讨论】:

【参考方案5】:

检查 facebook 的 java API。

其他示例:http://code.google.com/p/facebook-java-api/wiki/Examples

【讨论】:

我不相信 facebook-java-api 3.0.4 是最新的 FB 身份验证文档。相反,我按照接受的答案中的步骤操作,然后使用了 restfb 框架。 @s_t_e_v_e 我并不感到惊讶; FB 更频繁地更改他们的 API,而不是模特换衣服 ;) 很高兴听到你找到了解决方案 :)

以上是关于如何使用 OAuth 使用 Facebook 帐户登录 Google App Engine 的 Java 示例的主要内容,如果未能解决你的问题,请参考以下文章

Oauth - Facebook/Twitter/Foursquare

Rails Oauth 设计 Omniauth

通过第三方服务授权后,如何使用 OAuth 2.0 保持会话? [关闭]

使用 Facebook iPhone SDK 时如何刷新 oauth 令牌

来自 Facebook for App 的通知 - 此帐户已将增强的定位数据设置为关闭

如何计算服务帐户的 OAuth 签名?