JSP (tomcat) 中的 Facebook Connect 示例

Posted

技术标签:

【中文标题】JSP (tomcat) 中的 Facebook Connect 示例【英文标题】:Facebook Connect example in JSP (tomcat) 【发布时间】:2011-07-08 06:48:19 【问题描述】:

我正在构建一个 JSP 应用程序,我想使用 Facebook Connect 作为用户注册和身份验证的一种途径,但我没有找到太多关于如何获取和解析 FB cookie 甚至正确流程的信息。我正在尝试将官方documentation 中的信息与this one 等分步指南合并,但适用于Java。我不反对依赖像 Social Java 这样的库,但理解这些步骤会有所帮助。以下是我试图满足的 3 个用例。

    我网站上未经身份验证/未注册的用户点击“Facebook Connect”按钮进行注册(获取电子邮件、姓名和个人资料 ID)并登录。 未经身份验证的用户单击“Facebook Connect”按钮在我的域上创建有效会话。 没有连接 Facebook 个人资料的经过身份验证和注册的用户点击“Facebook Connect”并将 Facebook 个人资料 ID(以及更新其电子邮件和姓名的选项)与他们现有的个人资料相关联。

对于这个项目,我有一个看起来像这样的 Profile 类(我正在使用出色的 Project Lombok 和 Hibernate)

@Entity
@Data
public class Profile implements java.io.Serializable 
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;

  private String username;
  private String password;
  private String displayName;
  private String email;
  private String zipCode;
  private String mobileNumber;
  private String facebookId;

  @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
  private DateTime dateCreated;

  private int status;
  private int level;

Status 和 Level 确实应该是枚举,但我试图让这个问题的代码很小。

免责声明:我已经阅读了很多关于如何设置 Facebook Connect 以进行用户注册和身份验证的博客,但它们大部分是基于 php 和旧版本的Facebook API(甚至一些 SO 问题在他们接受的答案中指向旧 wiki)。这似乎是 SO 社区的完美应用。

【问题讨论】:

【参考方案1】:

这是我使用的 servlet 解决方案。只需稍加调整,您就可以使用简单的用户名-密码形式使其在任何 JSP 中工作。不需要javascript!!! 至于地址和电话号码,请阅读以下内容: http://developers.facebook.com/blog/post/447

FBAuthServlet

public class FBAuthServlet extends HttpServlet 

private static final Logger log = Logger.getLogger(FBAuthServlet.class);

private static final long serialVersionUID = 1L;

private UserService userService = //here goes your user service implementation

public FBAuthServlet() 
    super();


public void destroy() 
    super.destroy(); // Just puts "destroy" string in log
    // Put your code here


public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    if ("y".equals(request.getParameter("FacebookLogin"))) 
        response.sendRedirect(FaceBookConfig.getLoginRedirectURL());
        return;
    
    String code = req.getParameter("code");
    if (StringUtil.isNotBlankStr(code)) 
        String authURL = FaceBookConfig.getAuthURL(code);
        URL url = new URL(authURL);
        try 
            String result = readURL(url);
            String accessToken = null;
            Integer expires = null;
            String[] pairs = result.split("&");
            for (String pair : pairs) 
                String[] kv = pair.split("=");
                if (kv.length != 2) 
                    res.sendRedirect(FaceBookConfig.MAINURL);
                 else 
                    if (kv[0].equals("access_token")) 
                        accessToken = kv[1];
                    
                    if (kv[0].equals("expires")) 
                        expires = Integer.valueOf(kv[1]);
                    
                
            

            if (accessToken != null && expires != null) 

                User user = authFacebookLogin(accessToken, request.getRemoteAddr());
                if (user != null && user.getFacebookId() != null) 
                    //forward to spring security filter chain
                    res.sendRedirect(FaceBookConfig.MAINURL + "/j_spring_security_check?j_username=" + user.getEmail() + "&FaceBookId=" + user.getFacebookId());
                 else if (user != null && StringUtil.isNullOrBlank(user.getFacebookId())) 
                    res.sendRedirect(FaceBookConfig.MAINURL + "/login.html?login_error=You are not Registered By Facebook Connect");

                 else 
                    res.sendRedirect(FaceBookConfig.MAINURL);
                
            
         catch (Exception e) 
            e.printStackTrace();
            res.sendRedirect(FaceBookConfig.MAINURL);
        
    



public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 
    doGet(request, response);


public void init() throws ServletException 


private String readURL(URL url) throws IOException 
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    InputStream is = url.openStream();
    int r;
    while ((r = is.read()) != -1) 
        baos.write(r);
    
    return new String(baos.toByteArray());



private User authFacebookLogin(String accessToken, String ip) 
    try 
        String content = IOUtil.urlToString(new URL("https://graph.facebook.com/me?access_token=" + accessToken));

        JSONObject resp = new JSONObject(content);
        String facebookid = resp.getString("id");
        String firstName = resp.getString("first_name");
        String lastName = resp.getString("last_name");
        String email = resp.getString("email");

        log.info("Facebook response: " + content);

        CreateUserRequestCommand comm = new CreateUserRequestCommand();

        comm.setEmail(email);
        comm.setFacebookId(facebookid);
        comm.setFirst(StringAndDateUtils.safeChar(firstName));
        comm.setLast(StringAndDateUtils.safeChar(lastName));
        //if success login
        if (userService.getUserByEmail(email) == null) 
            //if first time login
            User u = userService.createUser(comm, ip);
            return u;
         else //if existed
            User existedUser = userService.getUserByEmail(email);
            return existedUser;

        
     catch (Throwable ex) 
        ex.printStackTrace();
    

    return null;


FBEnableServlet

public class FBEnableServlet extends HttpServlet 

private static final long serialVersionUID = 1L;

private UserService userService = (UserService) ServiceLocator.getContext().getBean("userService");

public FBEnableServlet() 
    super();


public void destroy() 
    super.destroy(); // Just puts "destroy" string in log
    // Put your code here


public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    if ("y".equals(request.getParameter("EnableFacebookConnect"))) 
        response.sendRedirect(FaceBookConfig.getEnableRedirectURL());
        return;
    
    String code = req.getParameter("code");
    if (StringUtil.isNotBlankStr(code)) 
        String authURL = FaceBookConfig.getEnableAuthURL(code);
        URL url = new URL(authURL);
        try 
            String result = readURL(url);
            String accessToken = null;
            Integer expires = null;
            String[] pairs = result.split("&");
            for (String pair : pairs) 
                String[] kv = pair.split("=");
                if (kv.length != 2) 
                    res.sendRedirect(FaceBookConfig.MAINURL);
                 else 
                    if (kv[0].equals("access_token")) 
                        accessToken = kv[1];
                    
                    if (kv[0].equals("expires")) 
                        expires = Integer.valueOf(kv[1]);
                    
                
            

            if (accessToken != null && expires != null) 
                User user = authFacebookLogin(accessToken, request.getRemoteAddr());
                String loginedEmail = "";
                try 
                    loginedEmail = SecurityContextHolder.getContext().getAuthentication().getName();
                 catch (Exception ex) 

                
                System.out.println("Logined email = " + loginedEmail);
                System.out.println("Facebook Login email = " + user.getEmail());
                if (user != null && user.getFacebookId() != null && user.getEmail().equals(loginedEmail)) 
                    userService.setFaceBookid(user.getFacebookId());
                    //forward to spring security filter chain
                    res.sendRedirect(FaceBookConfig.MAINURL + "/j_spring_security_check?j_username=" + user.getEmail() + "&FaceBookId=" + user.getFacebookId());
                 else 
                    res.sendRedirect(FaceBookConfig.MAINURL + "/secure/myAccount.html?message=Please login Facebook with same Email,you Login with " + user.getEmail());
                
            
         catch (Exception e) 
            e.printStackTrace();
            res.sendRedirect(FaceBookConfig.MAINURL);
        
    



public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 
    doGet(request, response);


public void init() throws ServletException 


private String readURL(URL url) throws IOException 
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    InputStream is = url.openStream();
    int r;
    while ((r = is.read()) != -1) 
        baos.write(r);
    
    return new String(baos.toByteArray());



private User authFacebookLogin(String accessToken, String ip) 
    try 
        String content = IOUtil.urlToString(new URL("https://graph.facebook.com/me?access_token=" + accessToken));

        JSONObject resp = new JSONObject(content);
        String facebookid = resp.getString("id");
        String email = resp.getString("email");

        User existedUser = userService.getUserByEmail(email);
        if (existedUser == null) 
            return null;
         else 
            existedUser.setFacebookId(facebookid);
            return existedUser;
        


     catch (Throwable ex) 
        ex.printStackTrace();
    

    return null;


【讨论】:

【参考方案2】:

我自己没用过,但是Google Code上好像有一个(非官方的)Java API:http://code.google.com/p/facebook-java-api/

【讨论】:

回复得真快!感谢您的指点,我现在正在查看该库的示例。我看到一个 SO 回答表明该项目不再被维护,但快速检查签入活动表明并非如此。 是的,我也找到了答案,但因为它是从 09 开始的,所以我试了一下,该项目的活动处于中等水平。祝你好运,HTH【参考方案3】:

自己进行集成并不需要很长时间,它只是 OAuth 2.0,然后是一些用户详细信息的 http 请求(json 格式)。

我们在 github 中有一些代码(与我们的社交模型非常相关),用于检查 OAuth 令牌并返回用户 ID(链接在帖子底部)。您可以从 Facebook Connect JavaScript 写入的 cookie 中获取当前用户的访问令牌(cookie 名称以“fbs_”开头)。

https://github.com/mbst/common-social/blob/master/src/main/java/com/metabroadcast/common/social/auth/facebook/FacebookAccessTokenChecker.java

【讨论】:

不幸的是,您指向该存储库的链接不再存在。 :(

以上是关于JSP (tomcat) 中的 Facebook Connect 示例的主要内容,如果未能解决你的问题,请参考以下文章

tomcat中的JSP引擎

TomCat 中的 JSP 文件编码

Tomcat中的超级开发模式+ JSP页面

Tomcat正常启动,可以访问tomcat主页,却不能访问webapp中的项目的jsp文件,这是啥原因?

Tomcat(.jsp)

jsp 访问文件夹中的图片,tomcat配置虚拟目录