第一次接触Facebook第三方登录,可能有些地方做的并不全面,只是尝试着做了一个小demo,因为国内接入Facebook的项目并不多,并且多数都是Android或IOS的实现,所以资料也特别少,在此做个小总结。
第三方登录主要就是OAuth2.0协议,了解OAuth2.0是必要的!
开发流程:
1、了解OAuth2.0
2、到Facebook官网注册开发者账号,创建应用
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.
②认证授权过程
2、到Facebook官网注册开发者账号,创建应用
①要登录www.facebook.com毫无疑问需要FQ,这个如果不会的话问问身边的其他人总有人会的
②注册Facebook开发者账号这个就到官网一步一步来就好了,属于傻瓜式注册账号
③创建应用成功后会给你一个应用编号和应用秘钥,这两个要保留在代码中会用到
创建应用还需要填写一些网址什么的,我给同学们标识几个重要的地方:
<1>创建成功之后的页面,应用编号和秘钥一定要妥善保存到代码中
<2>在设置>基本中配置应用域名,访问应用时的域名,随便写一个配置到hosts文件中即可,不会的看下图:
<3>你的网站的入口访问地址
<4>如图这样配置就可以,那个跳转网址是用户登录成功之后回调的地址(不明白的接着往下走,有个印象就行,这个随时可以改)
基本上这些都配置好了就可以开始写代码了
3、代码实现(分为两类同学,分别找对应自己的实现方式)
【靠自己】想自主实现的同学,我截图具体位置,慢慢摸索同样可以做出来
想在后台做验证的同学看这里(这种方式比较安全,且可扩展性强,不需要调用facebookAPI)
想都在网页上实现的同学看这里
【无力者】不想自己找文档,不想思考,着急做的同学,看我上传的代码,复制粘贴就可以了
①我的index.jsp(对应我的应用的网址)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
登录页面
Login Page
②controller代码
package com.lenovo.login.controller;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @ClassName: TestController
* @Description: FaceBook第三方登录
* @date Mar 15, 2017
*/
@Controller
public class TestController {
//应用编号
private static String client_id="应用编号";
//应用秘钥
private static String client_secret="应用秘钥";
//表示取得的用户信息的权限范围
private static String scope = "user_about_me,email,read_stream";
//回调地址
private static String redirect_url ="http://gntina.iok.la/doLogin";
//获取临时口令
private static String code_url="https://www.facebook.com/v2.8/dialog/oauth";
//获取访问口令
private static String token_url="https://graph.facebook.com/v2.8/oauth/access_token";
//获取用户信息
private static String user_url="https://graph.facebook.com/me";
//验证口令
private static String verify_url="https://graph.facebook.com/debug_token";
//获取应用口令
private static String app_url="https://graph.facebook.com/v2.8/oauth/access_token";
//第一步访问登录页面
@RequestMapping(value="/index")
public String toIndex(HttpServletRequest request){
return "index";
}
/**
* @throws IOException
* @Title: doLogin
* @Description: 调用“登录”对话框和设置重定向网址
* @return void 这个就是在应用中定义的跳转网址,也就是重定向第二步之后回调的地址,并且带上了code参数
* @date Mar 17, 2017 9:29:03 AM
* @throws
*/
@RequestMapping(value="/doLogin")
@ResponseBody
public Object doLogin(HttpServletRequest request,HttpServletResponse response) throws IOException{
String code = request.getParameter("code");//第二步获取code,迷糊的同学往下看,方法上也有对应的步骤
if(StringUtils.isNotBlank(code)){
String accessToken = getFacebookAccessToken(code);//第三步,用code(临时口令)换取accessToken
JSONObject userInfo=null;
if(StringUtils.isNotBlank(accessToken)){
userInfo = getUserInfo(accessToken);//第四步,用accessToken获取用户信息
}else{
System.out.println("accessToken is null");
}
System.out.println(userInfo);
return userInfo;
//对用户信息进行处理
}else{
return "/code";
}
}
/**
* @throws ServletException
* @throws IOException
* @Title: getAuthorizationCode
* @Description: 获取 Authorization Code(临时口令)
* @author 第二步,在index.jsp中用户登录成功后就是跳转到这里,重定向此地址会在回调地址中的参数带上code
* @return String
* @date Mar 17, 2017 9:30:38 AM
* @throws
*/
@RequestMapping(value="/code")
public static void getAuthorizationCode(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException{
response.sendRedirect(code_url+"?client_id="+client_id+"&redirect_uri="+redirect_url);
}
/**
* @return
* @throws IOException
* @Title: getFacebookAccessToken
* @Description:用临时口令获取访问口令 access_token
* @author 第三步用code换取accessToken(调用的接口和参数在代码里找就能看明白了)
* @return String
* @param code“登录”对话框重定向接收的参数。
* @date Mar 15, 2017 11:36:11 AM
* @throws
*/
public static String getFacebookAccessToken(String code){
HashMap params = new HashMap();
params.put("client_id", client_id);
params.put("redirect_uri", redirect_url);
params.put("client_secret", client_secret);
params.put("code", code);
String[] responseResult =null;
String accessToken =null;
try {
responseResult = HttpClientUtil.getStringByPost(token_url, params, null);
} catch (Exception e) {
e.printStackTrace();
}
if (null != responseResult && responseResult[0].equals("200")) {
String result = responseResult[1];
JSONObject jsonObject = JSONObject.fromObject(result);
accessToken = jsonObject.getString("access_token");
}
return accessToken;
//获取,然后返回access_token
/*{
"access_token": {access-token},
"token_type": {type},
"expires_in": {seconds-til-expiration}
}*/
}
/**
* @throws IOException
* @return
* @Title: getUserInfo
* @Description:根据 token口令获取用户信息
* @author 第四步用accessToken获取用户信息(调用的接口和参数在代码里找就能看明白了)
* @return Map
* @date Mar 15, 2017 6:04:31 PM
* @throws
*/
public static JSONObject getUserInfo(String accessToken){
HashMap params = new HashMap();
String fields="id,name,birthday,gender,hometown,email,devices";
params.put("access_token", accessToken);
params.put("fields", fields);
String[] responseResult =null;
JSONObject userInfo=null;
try {
responseResult = HttpClientUtil.getStringByGet(user_url, params);
} catch (Exception e) {
e.printStackTrace();
}
if (null != responseResult && responseResult[0].equals("200")) {
String result = responseResult[1];
userInfo = JSONObject.fromObject(result);
}
return userInfo;
}
/**
* @Title: verifyToken
* @Description: 调用图谱API,验证口令 app_id 和 user_id 字段将帮助您的应用确认访问口令对用户和您的应用有效。
* @author 第五步验证访问的用户是否来自你的应用,防刷功能,防止恶意注册
* @return String
* @date Mar 17, 2017 9:50:38 AM
* @throws
*/
@RequestMapping("/verify")
@ResponseBody
public Object verifyToken(String accessToken){
HashMap params = new HashMap();
//检验口令
accessToken="EAATb6fZCbwXgBAFlUThSX7xWMcwfVhpT8A9szvYkWsTqhJDjcILOLkTPReDYHx6BfWl67MXA2ZApPyc7FEDJGJ1bIrM0u8zQI6nszrcnzULDRuUG2gBWIjuZAe6CPZCYXBHClpsL8zhZAK4gVZC4N27ZAkZBPDscRJW0bRS05LisJAZDZD";
//应用口令
String access_token=getAppToken();
params.put("input_token", accessToken);
params.put("access_token", access_token);
String[] responseResult =null;
String data = null ;
try {
responseResult = HttpClientUtil.getStringByGet(verify_url, params);
} catch (Exception e) {
e.printStackTrace();
}
if (null != responseResult && responseResult[0].equals("200")) {
String result = responseResult[1];
JSONObject jsonObject = JSONObject.fromObject(result);
data = jsonObject.getString("data");
System.out.println(data);
}
// {
// "data": {
// "app_id": 138483919580948,
// "application": "Social Cafe",
// "expires_at": 1352419328,
// "is_valid": true,
// "issued_at": 1347235328,
// "metadata": {
// "sso": "iphone-safari"
// },
// "scopes": [
// "email",
// "publish_actions"
// ],
// "user_id": 1207059
// }
// }
return data;
}
/**
* @Title: getAppToken
* @Description: 获取应用口令(用来验证口令是否来自我的应用)
* @author gaona
* @return String
* @date Mar 20, 2017 3:16:26 PM
* @throws
*/
public String getAppToken(){
HashMap params = new HashMap();
params.put("client_id", client_id);
params.put("client_secret", client_secret);
params.put("grant_type", "client_credentials");
String[] responseResult =null;
String appToken=null;
try {
responseResult = HttpClientUtil.getStringByGet(app_url, params);
} catch (Exception e) {
e.printStackTrace();
}
if (null != responseResult && responseResult[0].equals("200")) {
String result = responseResult[1];
JSONObject jsonObject = JSONObject.fromObject(result);
appToken = jsonObject.getString("access_token");
System.out.println(appToken);
}
return appToken;
}
}
上面的代码只是个demo,具体的逻辑和实现方式还要代码风格,就要靠同学们弄懂原理和流程后自己来决定了!
希望此文可以帮助到需要的同学,有不明白的地方欢迎随时留言!
写博客实在是太累了,下面关于Google第三方登录的和这个是一样的,不同的只是调用接口的地址和参数略有不同,有不放心的同学,我会抓紧时间补上的。
补:这两天又看了一下,换成SDK的方式更简单,直接调用facebook写好的代码,可以实现自动验证,也是一个不错的选择!
facebook.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Facebook Login Page
Login Page
controller
@RequestMapping(value = "/userInfo")
@ResponseBody
public String getUserInfo(String userInfo) {
System.out.println(userInfo);
return userInfo;
}
直接在页面上完成SDK的调用,把用户信息传回后台即可。