流程图:
facebook返回的数据:
/*从facebook返回的个人json数据,为了更方便看使用js文件格式化了一下*/ var info = { "location" : { "id" : "197604863587708", "name" : "四川成都" }, "locale" : "en_US", "link" : "http://www.facebook.com/couplecross", "sports" : [ { "id" : "108614982500363", "name" : "Basketball" } ], "education" : [ { "school" : { "id" : "110480755647045", "name" : "**中学" }, "type" : "High School" }, { "concentration" : [ { "id" : "107712559258737", "name" : "软件工程" } ], "school" : { "id" : "109354635749672", "name" : "**大学" }, "type" : "College" } ], "updated_time" : "2012-02-14T09:27:55+0000", "id" : "100002906766192", "first_name" : "张", "username" : "couplecross", "timezone" : 8, "bio" : "性格诡异,长相抽象;勤于思考,喜欢小创意!", "email" : "[email protected]", "verified" : true, "name" : "张三", "last_name" : "三", "gender" : "male" }
FacebookLoginFilter.java
package com.hydom.filter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONException; import org.json.JSONObject; import com.hydom.entity.User; import com.visural.common.IOUtil; /** * 功能:
* 1.方法的代码顺序就代表了执行过程;
* 2.每一个方法代表了一个执行步骤;
* 3.每一个方法的注释就说明了这个方法的功能点;
* 4.方法彼此相互关联:下一个方法依靠上一个方法的执行结果;
* * @author [email protected]
* @date 2012-2-23
* @version 1.0
* */ public class FacebookLoginFilter extends BaseFilter { private String app_id; private String secret; private String app_url; private static final Log log = LogFactory.getLog(FacebookLoginFilter.class); User user; /** * 系統初始化的時候就賦值這三個參數
* 当然这三个参数是可以通过配置文件来做,为了简便就直接赋值了 */ @Override public void init(FilterConfig arg0) { app_id = "323109261075221"; secret = "796684bfbb7594a6c599d12046c492a6"; app_url = "http://192.168.0.27:8080/facebookLogin"; } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; HttpSession session = request.getSession(true); session.setMaxInactiveInterval(-1); session.setAttribute("appId", app_id); session.setAttribute("secret", secret); session.setAttribute("appUrl", app_url); String code = request.getParameter("code"); if (null != code) { String accessToken = (String) session.getAttribute("accessToken"); Integer expires = (Integer) session.getAttribute("expires"); //accessToken这值session没有才进行获取授权 if ((null == accessToken || "".equals(accessToken.trim())) || null == expires) { /** * 示例readURL返回结果,说明为什么要这样写下面的代码:
* result:
* access_token= * AAAD3oVisZAtEBAHWN886RlkMkaYlS85Xpg50M6QvZAZAgaa
* Pc1fmA322LEefPnzYb47plXgIQBccTsqE7R64uiw * DMNvT0rhAOtuCPKXAl8o7LeNSjeT
* &expires=5558 */ URL authUrl = getAuthUrlByCode(code); String result = getAccessTokenByAuthUrl(authUrl); log.info("facebook登录的时候读取授权URL后的返回内容:\n" + result); String[] pairs = result.split("&"); String[] keyValue; for (String pair : pairs) { keyValue = pair.split("="); if (keyValue.length != 2) { log.error("facebook访问授权URL获取keyValue对出错,原因:\n", new RuntimeException("Unexpected auth response")); } else { //获取accessToken if (keyValue[0].equals("access_token")) { accessToken = keyValue[1]; if (accessToken != null) { //将accessToken放入session,避免重复获取 session.setAttribute("accessToken",accessToken); JSONObject json = getFacebookUserJsonByAccessToken(accessToken); user = localizeFacebookUser(json); session.setAttribute("localisedFacebookUser", user); } else { log.info("facebook 获取accessToken失败:\naccessToken="+ accessToken); } } //获取expires if (keyValue[0].equals("expires")) { expires = Integer.valueOf(keyValue[1]); //将expires放入session,避免重复获取 session.setAttribute("expires", expires); } } } } chain.doFilter(request, response); } else { chain.doFilter(request, response); } } /** * 根据code参数获取授权Url * * @param code * 地址栏的参数 * @return */ private URL getAuthUrlByCode(String code) { String url = "https://graph.facebook.com/oauth/access_token?client_id=" + app_id + "&redirect_uri=" + app_url + "&client_secret=" + secret + "&code=" + code; log.info("facebook登录获取授权URL时访问的URL:\n" + url); try { return new URL(url); } catch (MalformedURLException e) { log.error("facebook登录获取授权URL时访问的URL出错:\n", e); return null; } } /** * 根据授权Url获取访问标记accessToken和有效期限expires
* 这样在后台进行也是为了安全考虑,而不是http的get/post * * @param url * 授权Url * @return */ private String getAccessTokenByAuthUrl(URL url) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { InputStream is = url.openStream(); int r; while ((r = is.read()) != -1) { baos.write(r); } } catch (IOException e) { log.error("facebook登录的时候读取URL失败,原因:\n", e); } return new String(baos.toByteArray()); } /** * 根据获得的访问标记accessToken访问获取用户个人信息的json数据 * * @param accessToken * 访问标记 * @return */ private JSONObject getFacebookUserJsonByAccessToken(String accessToken) { try { JSONObject resp = new JSONObject(IOUtil .urlToString(new URL( "https://graph.facebook.com/me?access_token=" + accessToken))); log.info("根据访问标记accessToken访问获取用户个人信息的json数据:\n"+resp.toString()); return resp; } catch (Throwable ex) { throw new RuntimeException("failed login", ex); } } /** * 根据用户个人信息的json数据,进行我们需要的本地化处理,比如:存入数据库等等 * * @param json * 用户个人信息的json数据 * @return */ private User localizeFacebookUser(JSONObject json) { user = new User(); try { String name = json.getString("name"); if (name != null) user.setName(name); else user.setName("no register name"); user.setUserName(json.getString("username")); user.setEmail(json.getString("email")); user.setSnsId(json.getString("id")); } catch (JSONException e) { log.error("解析facebook返回的json数据失败:\n", e); } return user; } }
.