Facebook 授权登录(服务端)
一、Facebook配置
1、注册开发者
在facebook开发者官网注册成开发者
2、创建应用
点击右上角->我的应用->创建应用
3、获取应用编号、应用密钥
4、开通登录
- 点击左边产品->添加产品->登录
- 一般我们只需要名字、邮箱,权限部分不需要增加,如果有需要自行添加
5、记录应用编号、应用密钥后续开发使用
二、Facebook 授权登录时序图
三、Facebook 授权登录相关官方文档
1、官方文档地址
https://developers.facebook.com/docs/graph-api
2、校验token地址
- 校验token地址的文档地址
- 接口地址
https://graph.facebook.com/debug_token?access_token=ACCESS-TOKEN&input_token={User-token} - 注意事项
接口中的access_token和input_token 均是客户端传递的token值
3、获取用户信息地址
- 获取用户信息的文档地址
- 接口地址
https://graph.facebook.com/USER-ID?fields=id,name,email,picture&access_token=ACCESS-TOKEN - 注意事项
接口中的access_token指的是前面配置中获取的应用编号和应用密钥组合,值为{Your AppId}|{Your AppSecret}, 记得请求路径做urlEncode
参考代码
校验token合法性
private static final String CHECK_TOKEN_URL = "https://graph.facebook.com/debug_token?access_token=%s&input_token=%s";
/**
* 校验用户token释放非法
* @param unionId 用户唯一标识
* @param token 用户授权token
*/
private Integer checkTokenValid(String unionId, String token) {
String checkTokenUrl = String.format(CHECK_TOKEN_URL, token, token);
ResponseEntity<String> checkTokenResponse = restTemplate.getForEntity(checkTokenUrl, String.class);
if (!checkTokenResponse.getStatusCode().is2xxSuccessful()) {
log.error("facebook请求校验接口失败,响应为{}", checkTokenResponse.getStatusCode());
return -1;
}
JsonNode checkTokenResponseNode = JsonUtil.fromJson(checkTokenResponse.getBody(), JsonNode.class);
JsonNode data = checkTokenResponseNode.get("data");
if (!unionId.equals(Optional.ofNullable(data).map(it -> it.get("user_id")).map(JsonNode::asText).orElse(""))) {
log.error("用户传递的唯一标识非法,unionId is {},data is {}", unionId, checkTokenResponse.getBody());
return -1;
}
if (!Optional.ofNullable(data).map(it -> it.get("is_valid")).map(JsonNode::asBoolean).orElse(Boolean.FALSE)) {
log.error("用户传递的唯一标识过期,unionId is {},data is {}", unionId, checkTokenResponse.getBody());
return -1;
}
return 1;
}
获取用户信息
private static final String USER_INFO_URL = "https://graph.facebook.com/%s?access_token=%s&fields=id,name,picture,email";
private Map<String,String> getThirdPartyLoginUserBO(String unionId) {
String getUserInfoUrl = String.format(USER_INFO_URL, unionId, getAccessToken());
ResponseEntity<String> userInfoResponse = restTemplate.getForEntity(getUserInfoUrl, String.class);
if (!userInfoResponse.getStatusCode().is2xxSuccessful()) {
log.error("facebook请求查询用户接口失败,响应为{}", userInfoResponse.getStatusCode());
return Collections.emptyMap();
}
JsonNode userInfoResponseNode = JsonUtil.fromJson(userInfoResponse.getBody(), JsonNode.class);
Map<String,String> thirdPartyLoginUser =new HashMap<>(4);
thirdPartyLoginUser.put("unionId",userInfoResponseNode.get("id").asText());
thirdPartyLoginUser.put("userName",userInfoResponseNode.get("name").asText());
//用户的email可能为空
thirdPartyLoginUser.put("email",userInfoResponseNode.at("/email").asText());
//用户的头像可能为空
thirdPartyLoginUser.put("avatar",userInfoResponseNode.at("/picture/data/url").asText());
return thirdPartyLoginUser;
}
private String getAccessToken() {
//accessToken的组成为clientId|clientSecret,由于urlEncode |变为%7C
return clientId + "%7C" + clientSecret;
}