且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-12-04 16:34:24

以下是我在 App Engine 上的做法:

Here is how I do it on App Engine:

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

Step 1) Register an "app" on Facebook (cf. https://developers.facebook.com/ ). You give Facebook a name for the app and a url. The url you register is the url to the page (jsp or servlet) that you want to handle the login. From the registration you get two strings, an "app ID" and an "app secret" (the latter being your password, do not give this out or write it in html).

在这个例子中,假设我注册的 url 是http://myappengineappid.appspot.com/signin_fb.do".

For this example, let's say the url I register is "http://myappengineappid.appspot.com/signin_fb.do".

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

2) From a webpage, say with a button, you redirect the user to the following url on Facebook, substituting your app id for "myfacebookappid" in the below example. You also have to choose which permissions (or "scopes") you want the ask the user (cf. https://developers.facebook.com/docs/reference/api/permissions/ ). In the example I ask for access to the user's email only.

(要知道的一个有用的事情是,您还可以传递一个可选字符串,该字符串将在状态"参数中原封不动地返回.例如,我传递了用户的数据存储键,这样我就可以在 Facebook 通过时检索用户钥匙还给我.我在例子中没有这样做.)

(A useful thing to know is that you can also pass along an optional string that will be returned unchanged in the "state" parameter. For instance, I pass the user's datastore key, so I can retrieve the user when Facebook passes the key back to me. I do not do this in the example.)

这是一个jsp片段:

<%@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,并被要求批准您请求的权限.然后,用户将被重定向回您注册的网址.在此示例中,这是http://myappengineappid.appspot.com/signin_fb.do" 在我的 web.xml 中映射到以下 servlet:

3) Your user will be forwarded to Facebook, and asked to approve the permissions you ask for. Then, the user will be redirected back to the url you have registered. In this example, this is "http://myappengineappid.appspot.com/signin_fb.do" which in my web.xml maps to the following 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 + "
");            
            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 + "
");            
            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 的应用机密.

I have removed error handling code, as you may want to handle it differently than I do. (Also, "Gender" is of course a class that I have defined.) At this point, you can use the data for whatever you want, like registering a new user or look for an existing user to log in. Note that the "myfacebookappsecret" string should of course be your app secret from Facebook.

您需要org.json"包才能使用此代码,您可以在以下位置找到该代码:http:///json.org/java/(只需将 .java 文件添加到 org/json 文件夹结构中的代码中即可).

You will need the "org.json" package to use this code, which you can find at: http://json.org/java/ (just take the .java files and add them to your code in an org/json folder structure).

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

I hope this helps. If anything is unclear, please do comment, and I will update the answer.

Ex animo,-亚历山大.

Ex animo, - Alexander.

****更新****

我想补充一些信息,如果其中一些看起来有点过分,我深表歉意.

I want to add a few tidbits of information, my apologies if some of this seems a bit excessive.

为了能够通过他/她的 Facebook 帐户登录用户,您需要知道我们正在谈论的数据存储中的哪个用户.如果它是一个新用户,很容易,创建一个新的用户对象(带有一个名为facebookId"的字段,或者任何你想调用的字段,你从 Facebook 获取它的值),将它保存在数据存储中并让用户登录.

To be able to log in a user by his/her Facebook account, you need to know which user in the datastore we are talking about. If it's a new user, easy, create a new user object (with a field called "facebookId", or whatever you want to call it, whose value you get from Facebook), persist it in the datastore and log the user in.

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

If the user exist, you need to have the field with the facebookId. When the user is redirected from Facebook, you can grab the facebookId, and look in the datastore to find the user you want to log in.

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

If you already have users, you will need to let them log in the way you usually do, so you know who they are, then send them to Facebook, get the facebookId back and update their user object. This way, they can log in using Facebook the next time.

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

Another small note: The user will be presented with a screen on Facebook asking to allow your app access to whatever scopes you ask for, there is no way around this (the less scopes you ask for, the less intrusive it seems, though). However, this only happens the first time a user is redirected (unless you ask for more scopes later, then it'll ask again).