java网站如何集成facebook第三方登录

时间:2024-03-22 08:05:01

第一次接触Facebook第三方登录,可能有些地方做的并不全面,只是尝试着做了一个小demo,因为国内接入Facebook的项目并不多,并且多数都是AndroidiOS的实现,所以资料也特别少,在此做个小总结。

第三方登录主要就是OAuth2.0协议,了解OAuth2.0是必要的!

开发流程:

1、了解OAuth2.0

2、到Facebook官网注册开发者账号,创建应用(开发者平台(https://developers.facebook.com),如果尚未注册账号的请注册账号并进行登录)

3、代码实现

下面逐步介绍

1、了解OAuth2.0(摘自百度百科)

①定义

【百度】OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的。oAuth是Open
Authorization的简写。

【官网】

OAuth 2.0 is the industry-standard
protocol for authorization. OAuth 2.0 supersedes the work done on the
original OAuth protocol created in 2006. OAuth 2.0 focuses on client
developer simplicity while providing specific authorization
flows for web applications, desktop applications, mobile phones, and
living room devices. This specification is being developed within theIETF OAuth WG.

②认证授权过程

【概念】在认证和授权的过程中涉及的三方包括:
<1>服务提供方(Facebook),用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表。
<2>用户,存放在服务提供方的受保护的资源的拥有者。
<3>客户端(我们的应用),要访问服务提供方资源的第三方应用,通常是网站。在认证过程之前,客户端要向服务提供者申请客户端标识。
【过程】使用OAuth进行认证和授权的过程如下所示:
用户想操作存放在服务提供方的资源。
<1>用户登录客户端向服务提供方请求一个临时令牌。
<2>服务提供方验证客户端的身份后,授予一个临时令牌。
<3>客户端获得临时令牌后,将用户引导至服务提供方的授权页面请求用户授权。在这个过程中将临时令牌和客户端的回调连接发送给服务提供方。
<4>用户在服务提供方的网页上输入用户名和密码,然后授权该客户端访问所请求的资源。
<5>授权成功后,服务提供方引导用户返回客户端的网页。
<6>客户端根据临时令牌从服务提供方那里获取访问令牌。
<7>服务提供方根据临时令牌和用户的授权情况授予客户端访问令牌。
<8>客户端使用获取的访问令牌访问存放在服务提供方上的受保护的资源。
【图片】
图1:官网提供的认证流程   
java网站如何集成facebook第三方登录
图2:百度上搜个好看的给同学们理解
java网站如何集成facebook第三方登录
如果以上没看太明白的话不要紧,跟着我后面一步一步走,会慢慢理解的

2、到Facebook官网注册开发者账号,创建应用

①要登录www.facebook.com毫无疑问需要FQ,这个如果不会的话问问身边的其他人总有人会的

②注册Facebook开发者账号这个就到官网一步一步来就好了,属于傻瓜式注册账号

③创建应用成功后会给你一个应用编号和应用秘钥,这两个要保留在代码中会用到

创建应用还需要填写一些网址什么的,我给同学们标识几个重要的地方:

<1>创建成功之后的页面,应用编号和秘钥一定要妥善保存到代码中

java网站如何集成facebook第三方登录

<2>在设置>基本中配置应用域名,访问应用时的域名,随便写一个配置到hosts文件中即可,不会的看下图:

java网站如何集成facebook第三方登录

java网站如何集成facebook第三方登录java网站如何集成facebook第三方登录java网站如何集成facebook第三方登录

java网站如何集成facebook第三方登录

<3>你的网站的入口访问地址

java网站如何集成facebook第三方登录

<4>如图这样配置就可以,那个跳转网址是用户登录成功之后回调的地址(不明白的接着往下走,有个印象就行,这个随时可以改)

java网站如何集成facebook第三方登录

基本上这些都配置好了就可以开始写代码了

3、代码实现(分为两类同学,分别找对应自己的实现方式)

【靠自己】想自主实现的同学,我截图具体位置,慢慢摸索同样可以做出来

java网站如何集成facebook第三方登录

想在后台做验证的同学看这里(这种方式比较安全,且可扩展性强,不需要调用facebookAPI)

java网站如何集成facebook第三方登录

想都在网页上实现的同学看这里

java网站如何集成facebook第三方登录

【无力者】不想自己找文档,不想思考,着急做的同学,看我上传的代码,复制粘贴就可以了

①我的index.jsp(对应我的应用的网址)

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>登录页面</title>
  8. </head>
  9. <script type="text/javascript" src="/static/jquery-1.7.2.min.js"></script>
  10. <body>
  11. <h1>Login Page</h1>
  12. <form action="${pageContext.request.contextPath }/login">
  13. username: <input type="text" name="username"><br /> <br />
  14. password: <input type="password" name="password"><br /> <br />
  15. <input type="submit" value="登录">
  16. </form>
  17. <br />
  18. <fb:login-button scope="public_profile,email"
  19. onlogin="checkLoginState();"
  20. auto_logout_link="true"
  21. size="large"
  22. show_faces="true">
  23. </fb:login-button>
  24. <div id="status"></div>
  25. <script>
  26. // This is called with the results from from FB.getLoginStatus().
  27. function statusChangeCallback(response) {
  28. console.log('statusChangeCallback');
  29. console.log(response);
  30. if (response.status === 'connected') {
  31. <span style="color:#FF0000;">//到此代表用户登录成功</span>
  32. <span style="color:#FF0000;">//跳转到http://gntina.iok.la/code(参见我后台代码的路径)</span>
  33. location.href = "<span style="color:#FF0000;">发送重定向的地址</span>";
  34. } else {
  35. document.getElementById('status').innerHTML = 'Please log '
  36. + 'into this app.';
  37. }
  38. }
  39. function checkLoginState() {
  40. FB.getLoginStatus(function(response) {
  41. statusChangeCallback(response);
  42. });
  43. }
  44. window.fbAsyncInit = function() {
  45. FB.init({
  46. appId : '<span style="color:#FF0000;">应用编号</span>',
  47. cookie : true, // enable cookies to allow the server to access
  48. xfbml : true, // parse social plugins on this page
  49. version : 'v2.8' // use graph api version 2.8
  50. });
  51. FB.getLoginStatus(function(response) {
  52. statusChangeCallback(response);
  53. });
  54. };
  55. // Load the SDK asynchronously
  56. (function(d, s, id) {
  57. var js, fjs = d.getElementsByTagName(s)[0];
  58. if (d.getElementById(id))
  59. return;
  60. js = d.createElement(s);
  61. js.id = id;
  62. js.src = "//connect.facebook.net/en_US/sdk.js";
  63. fjs.parentNode.insertBefore(js, fjs);
  64. }(document, 'script', 'facebook-jssdk'));
  65. </script>
  66. </body>
  67. </html>

②controller代码

  1. package com.lenovo.login.controller;
  2. import java.io.IOException;
  3. import java.util.HashMap;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import net.sf.json.JSONObject;
  8. import org.apache.commons.lang.StringUtils;
  9. import org.springframework.stereotype.Controller;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.ResponseBody;
  12. /**
  13. * @ClassName: TestController
  14. * @Description: FaceBook第三方登录
  15. * @date Mar 15, 2017
  16. */
  17. @Controller
  18. public class TestController {
  19. //应用编号
  20. private static String client_id="<span style="color:#FF0000;">应用编号</span>";
  21. //应用秘钥
  22. private static String client_secret="<span style="color:#FF0000;">应用秘钥</span>";
  23. //表示取得的用户信息的权限范围
  24. private static String scope = "user_about_me,email,read_stream";
  25. //回调地址
  26. private static String redirect_url ="http://gntina.iok.la/doLogin";
  27. //获取临时口令
  28. private static String code_url="https://www.facebook.com/v2.8/dialog/oauth";
  29. //获取访问口令
  30. private static String token_url="https://graph.facebook.com/v2.8/oauth/access_token";
  31. //获取用户信息
  32. private static String user_url="https://graph.facebook.com/me";
  33. //验证口令
  34. private static String verify_url="https://graph.facebook.com/debug_token";
  35. //获取应用口令
  36. private static String app_url="https://graph.facebook.com/v2.8/oauth/access_token";
  37. <span style="color:#FF0000;"> //第一步访问登录页面</span>
  38. @RequestMapping(value="/index")
  39. public String toIndex(HttpServletRequest request){
  40. return "index";
  41. }
  42. /**
  43. * @throws IOException
  44. * @Title: doLogin
  45. * @Description: 调用“登录”对话框和设置重定向网址
  46. * @return void <span style="color:#FF0000;">这个就是在应用中定义的跳转网址,也就是重定向第二步之后回调的地址,并且带上了code参数</span>
  47. * @date Mar 17, 2017 9:29:03 AM
  48. * @throws
  49. */
  50. @RequestMapping(value="/doLogin")
  51. @ResponseBody
  52. public Object doLogin(HttpServletRequest request,HttpServletResponse response) throws IOException{
  53. String code = request.getParameter("code");<span style="color:#FF0000;">//第二步获取code,迷糊的同学往下看,方法上也有对应的步骤</span>
  54. if(StringUtils.isNotBlank(code)){
  55. String accessToken = getFacebookAccessToken(code);<span style="color:#FF0000;">//第三步,用code(临时口令)换取accessToken</span>
  56. JSONObject userInfo=null;
  57. if(StringUtils.isNotBlank(accessToken)){
  58. userInfo = getUserInfo(accessToken);<span style="color:#FF0000;">//第四步,用accessToken获取用户信息</span>
  59. }else{
  60. System.out.println("accessToken is null");
  61. }
  62. System.out.println(userInfo);
  63. return userInfo;
  64. //对用户信息进行处理
  65. }else{
  66. return "/code";
  67. }
  68. }
  69. /**
  70. * @throws ServletException
  71. * @throws IOException
  72. * @Title: getAuthorizationCode
  73. * @Description: 获取 Authorization Code(临时口令)
  74. * @author <span style="color:#FF0000;">第二步,在index.jsp中用户登录成功后就是跳转到这里,重定向此地址会在回调地址中的参数带上code  </span>
  75. * @return String
  76. * @date Mar 17, 2017 9:30:38 AM
  77. * @throws
  78. */
  79. @RequestMapping(value="/code")
  80. public static void getAuthorizationCode(HttpServletRequest  request,HttpServletResponse response) throws IOException, ServletException{
  81. response.sendRedirect(code_url+"?client_id="+client_id+"&redirect_uri="+redirect_url);
  82. }
  83. /**
  84. * @return
  85. * @throws IOException
  86. * @Title: getFacebookAccessToken
  87. * @Description:用临时口令获取访问口令 access_token
  88. * @author <span style="color:#FF0000;">第三步用code换取accessToken(调用的接口和参数在代码里找就能看明白了) </span>
  89. * @return String
  90. * @param code“登录”对话框重定向接收的参数。
  91. * @date Mar 15, 2017 11:36:11 AM
  92. * @throws
  93. */
  94. public static String getFacebookAccessToken(String code){
  95. HashMap<String, String> params = new HashMap<String,String>();
  96. params.put("client_id", client_id);
  97. params.put("redirect_uri", redirect_url);
  98. params.put("client_secret", client_secret);
  99. params.put("code", code);
  100. String[] responseResult =null;
  101. String accessToken =null;
  102. try {
  103. responseResult = HttpClientUtil.getStringByPost(token_url, params, null);
  104. } catch (Exception e) {
  105. e.printStackTrace();
  106. }
  107. if (null != responseResult && responseResult[0].equals("200")) {
  108. String result = responseResult[1];
  109. JSONObject jsonObject =  JSONObject.fromObject(result);
  110. accessToken = jsonObject.getString("access_token");
  111. }
  112. return accessToken;
  113. //获取,然后返回access_token
  114. /*{
  115. "access_token": {access-token},
  116. "token_type": {type},
  117. "expires_in":  {seconds-til-expiration}
  118. }*/
  119. }
  120. /**
  121. * @throws IOException
  122. * @return
  123. * @Title: getUserInfo
  124. * @Description:根据   token口令获取用户信息
  125. * @author <span style="color:#FF0000;">第四步用accessToken获取用户信息(调用的接口和参数在代码里找就能看明白了)</span>
  126. * @return Map<String,String>
  127. * @date Mar 15, 2017 6:04:31 PM
  128. * @throws
  129. */
  130. public static JSONObject getUserInfo(String accessToken){
  131. HashMap<String, String> params = new HashMap<String,String>();
  132. String fields="id,name,birthday,gender,hometown,email,devices";
  133. params.put("access_token", accessToken);
  134. params.put("fields", fields);
  135. String[] responseResult =null;
  136. JSONObject userInfo=null;
  137. try {
  138. responseResult = HttpClientUtil.getStringByGet(user_url, params);
  139. } catch (Exception e) {
  140. e.printStackTrace();
  141. }
  142. if (null != responseResult && responseResult[0].equals("200")) {
  143. String result = responseResult[1];
  144. userInfo =  JSONObject.fromObject(result);
  145. }
  146. return userInfo;
  147. }
  148. /**
  149. * @Title: verifyToken
  150. * @Description: 调用图谱API,验证口令  app_id 和 user_id 字段将帮助您的应用确认访问口令对用户和您的应用有效。
  151. * @author <span style="color:#FF0000;">第五步验证访问的用户是否来自你的应用,防刷功能,防止恶意注册  </span>
  152. * @return String
  153. * @date Mar 17, 2017 9:50:38 AM
  154. * @throws
  155. */
  156. @RequestMapping("/verify")
  157. @ResponseBody
  158. public Object verifyToken(String accessToken){
  159. HashMap<String, String> params = new HashMap<String,String>();
  160. //检验口令
  161. accessToken="EAATb6fZCbwXgBAFlUThSX7xWMcwfVhpT8A9szvYkWsTqhJDjcILOLkTPReDYHx6BfWl67MXA2ZApPyc7FEDJGJ1bIrM0u8zQI6nszrcnzULDRuUG2gBWIjuZAe6CPZCYXBHClpsL8zhZAK4gVZC4N27ZAkZBPDscRJW0bRS05LisJAZDZD";
  162. //应用口令
  163. String access_token=getAppToken();
  164. params.put("input_token", accessToken);
  165. params.put("access_token", access_token);
  166. String[] responseResult =null;
  167. String data = null ;
  168. try {
  169. responseResult = HttpClientUtil.getStringByGet(verify_url, params);
  170. } catch (Exception e) {
  171. e.printStackTrace();
  172. }
  173. if (null != responseResult && responseResult[0].equals("200")) {
  174. String result = responseResult[1];
  175. JSONObject jsonObject =  JSONObject.fromObject(result);
  176. data = jsonObject.getString("data");
  177. System.out.println(data);
  178. }
  179. //      {
  180. //          "data": {
  181. //              "app_id": 138483919580948,
  182. //              "application": "Social Cafe",
  183. //              "expires_at": 1352419328,
  184. //              "is_valid": true,
  185. //              "issued_at": 1347235328,
  186. //              "metadata": {
  187. //                  "sso": "iphone-safari"
  188. //              },
  189. //              "scopes": [
  190. //                  "email",
  191. //                  "publish_actions"
  192. //              ],
  193. //              "user_id": 1207059
  194. //          }
  195. //      }
  196. return data;
  197. }
  198. /**
  199. * @Title: getAppToken
  200. * @Description: 获取应用口令(用来验证口令是否来自我的应用)
  201. * @author gaona
  202. * @return String
  203. * @date Mar 20, 2017 3:16:26 PM
  204. * @throws
  205. */
  206. public String getAppToken(){
  207. HashMap<String, String> params = new HashMap<String,String>();
  208. params.put("client_id", client_id);
  209. params.put("client_secret", client_secret);
  210. params.put("grant_type", "client_credentials");
  211. String[] responseResult =null;
  212. String appToken=null;
  213. try {
  214. responseResult = HttpClientUtil.getStringByGet(app_url, params);
  215. } catch (Exception e) {
  216. e.printStackTrace();
  217. }
  218. if (null != responseResult && responseResult[0].equals("200")) {
  219. String result = responseResult[1];
  220. JSONObject jsonObject =  JSONObject.fromObject(result);
  221. appToken = jsonObject.getString("access_token");
  222. System.out.println(appToken);
  223. }
  224. return appToken;
  225. }
  226. }

上面的代码只是个demo,具体的逻辑和实现方式还要代码风格,就要靠同学们弄懂原理和流程后自己来决定了!

希望此文可以帮助到需要的同学,有不明白的地方欢迎随时留言!

写博客实在是太累了,下面关于Google第三方登录的和这个是一样的,不同的只是调用接口的地址和参数略有不同,有不放心的同学,我会抓紧时间补上的。

补:这两天又看了一下,换成SDK的方式更简单,直接调用facebook写好的代码,可以实现自动验证,也是一个不错的选择!

facebook.jsp

  1. <span style="color:#000000;"><%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html>
  4. <html>
  5. <head>
  6. <title>Facebook Login Page</title>
  7. <meta charset="UTF-8">
  8. </head>
  9. <script type="text/javascript" src="/static/jquery-1.7.2.min.js"></script>
  10. <script>
  11. //引入 facebook SDK
  12. (function(d, s, id) {
  13. var js, fjs = d.getElementsByTagName(s)[0];
  14. if (d.getElementById(id))
  15. return;
  16. js = d.createElement(s);
  17. js.id = id;
  18. js.src = "//connect.facebook.net/en_US/sdk.js";
  19. fjs.parentNode.insertBefore(js, fjs);
  20. }(document, 'script', 'facebook-jssdk'));
  21. </script>
  22. <body>
  23. <h1>Login Page</h1>
  24. <form action="${pageContext.request.contextPath }/login">
  25. username: <input type="text" name="username"><br /> <br />
  26. password: <input type="password" name="password"><br /> <br />
  27. <input type="submit" value="登录">
  28. </form><!-- 普通登录 -->
  29. <br />
  30. <fb:login-button scope="public_profile,email"
  31. onlogin="checkLoginState();"
  32. auto_logout_link="true"
  33. size="large"
  34. show_faces="true">
  35. </fb:login-button><!-- facebook 按钮 -->
  36. <div id="status"></div><!-- 登录状态显示 -->
  37. <script>
  38. function statusChangeCallback(response) {
  39. //可用于后台验证,但是前台调用SDK则会自动验证
  40. var accessToken=response.authResponse.accessToken;
  41. console.log(response.authResponse.accessToken);
  42. if (response.status === 'connected') {//sdk会自动保留accessToken,并且验证该请求是否来自我的应用
  43. FB.api('/me?fields=name,first_name,last_name,email', function(response) {
  44. //将用户信息传回服务端
  45. window.location.href="http://gntina.iok.la/userInfo?userInfo="+JSON.stringify(response);
  46. /* $.ajax({
  47. url:"http://gntina.iok.la/userInfo",
  48. data:{
  49. userInfo:JSON.stringify(response)
  50. },
  51. dataType:"json",
  52. async:false,
  53. success:function(data){
  54. window.location.href="";
  55. }
  56. }); */
  57. document.getElementById('status').innerHTML =
  58. 'Thanks for logging in, ' + response.name + '!';
  59. });
  60. } else {
  61. document.getElementById('status').innerHTML = 'Please log '
  62. + 'into this app.';
  63. }
  64. }
  65. function checkLoginState() {
  66. FB.getLoginStatus(function(response) {
  67. statusChangeCallback(response);
  68. });
  69. }
  70. window.fbAsyncInit = function() {
  71. FB.init({
  72. appId : '应用编号',
  73. cookie : true,
  74. xfbml : true,
  75. version : 'v2.8'
  76. });
  77. FB.getLoginStatus(function(response) {
  78. statusChangeCallback(response);
  79. });
  80. };
  81. </script>
  82. </body>
  83. </html></span>

controller

  1. @RequestMapping(value = "/userInfo")
  2. @ResponseBody
  3. public String getUserInfo(String userInfo) {
  4. System.out.println(userInfo);
  5. return userInfo;
  6. }

直接在页面上完成SDK的调用,把用户信息传回后台即可。

详细介绍请查看全文:https://cnblogs.com/qianzf/
原文博客的链接地址:https://cnblogs.com/qzf/