因为项目需求,需要用到facebook登录。facebook目前官方文档中,撑持的是js挪用faceboook sdk停止登录、注册等一系列操做,但是那里会吧facebook的APPID以及拜候密钥放入前端,形成应用平安性问题,所以我们在后端停止那些逻辑的挪用,会使平安性提拔。
1、起首需要注册一个facebook开发者账号
关于facebook账号注册,目前国内我暂时没有找到好的办法,因为账号注册号后,利用收集东西停止登录时,会被facebook官方检测到ip异常,招致封号。所以建议利用香港办事器(或者肆意海外办事器)停止该操做。比力费事。
2、账号注册好,去创建应用。
3、应用创建好,会给你应用的APPID和一串密钥。记住那两个工具,后面会用到。因为网页利用了谷歌翻译,所以有些名词可能会禁绝确。那里的法式应用域即应用域名,应用域名能够随意写一个,然后设置装备摆设到host文件中即可。
(host文件在 C:\Windows\System32\drivers\etc 那里)4、然后找到facebook登入
如图,将本页面设置为图中款式,然后设置装备摆设你写的facebook登录胜利后的回调地址。(那里的回调地址是你本身项目中的地址)
到那里facebook开发者设置装备摆设根本就完成了。后面就需要挪用facebook api,和编写本身的营业逻辑了。
那里贴上代码:
Controller层代码:
@UnAuth @ApiOperation(value = "查看脸书登录用户能否绑定", notes = "查看脸书登录用户能否绑定(不需要认证)") @PostMapping("/finduser") @ApiResponses({ @ApiResponse(code = 200, message = " -1 未传递参数 -2 已注册过多个用户 0 去注册 1 去登岸 -3 系统错误", response = Integer.class) }) public FacebookResult findUser(@RequestBody AuthRequest authRequest) { log.debug("authRequest:{}", authRequest); if (StringUtils.isEmpty(authRequest)) { log.debug("authRequest is null ...."); return new FacebookResult(-1, new Customer(), new FacebookResponse()); } try { FacebookResponse facebookResponse = JSONObject.toJavaObject(getUserInfo(authRequest.getAccessToken()), FacebookResponse.class); FacebookResult facebookResult = faceBookLoginService.checkUserBinding(facebookResponse, authRequest.getUserID()); if (facebookResult.getFlag() == 1) { LoginParams loginParams = new LoginParams(); loginParams.setUsername(facebookResult.getCustomer().getUserName()); //回调 loginParams.setConsumer(customer -> MobileLoginUtils.getInstance().putCustomerIdToSession(facebookResult.getCustomer().getId())); loginService.loginFb(loginParams); } return facebookResult; } catch (Exception e) { e.printStackTrace(); return new FacebookResult(-3, new Customer(), new FacebookResponse()); } } @UnAuth @ApiOperation(value = "脸书用户注册", notes = "脸书用户注册(不需要认证)") @PostMapping("/register") @ApiResponses({ @ApiResponse(code = 200, message = "-1 手机验证码错误 -2 手机号或验证码为空 -3 手机号存在 -4 邮箱格局错误 -5 二次密码不合错误 -6 昵称为空 -7 用户已有绑定账户 0 失败 胜利>0", response = Integer.class) }) public int registerFb(HttpServletRequest request, @RequestBody RegisterData registerData) { int res = 0; try { res = checkRegister(registerServiceApi.registerCustomer( registerData.getMobile(), registerData.getPassword(), registerData.getRepassword(), registerData.getCode(), (String) (request.getSession().getAttribute(String.format("%s_%s", CommonConstant.MOBILE_REGISTER_CODE_KEY, registerData.getMobile()))), registerData.getEmail(), registerData.getNickname(), registerData.getUserId()), request, registerData.getMobile()); } catch (Exception e) { e.printStackTrace(); return res; } return res; } /** * 胜利请除session中的手机验证码 * * @param res 返回码 * @param mobile 手机号码 */ private int checkRegister(int res, HttpServletRequest request, String mobile) { if (res > 0) { request.getSession().removeAttribute(String.format("%s_%s", CommonConstant.MOBILE_REGISTER_CODE_KEY, mobile)); } return res; } public static JSONObject getUserInfo(String accessToken) { HashMap<String, String> params = new HashMap<String, String>(); String fields = "id,name,email"; params.put("access_token", accessToken); params.put("fields", fields); String responseResult = null; JSONObject userInfo = null; try { responseResult = HttpClientUtil.doGet("https://graph.facebook.com/me", params); } catch (Exception e) { responseResult = "fail"; e.printStackTrace(); } if (!StringUtils.isEmpty(responseResult)) { userInfo = JSONObject.parseObject(responseResult); } return userInfo; } /** * 用户注册实体 */ @Data @ApiModel(description = "用户注册实体") private static class RegisterData { /** * 手机号码 */ @ApiModelProperty(value = "手机号码") private String mobile; /** * 密码 */ @ApiModelProperty(value = "密码") private String password; /** * 密码 */ @ApiModelProperty(value = "反复密码") private String repassword; /** * 手机验证码 */ @ApiModelProperty(value = "手机验证码") private String code; /** * 邮箱 */ @ApiModelProperty(value = "邮箱") private String email; /** * 昵称 */ @ApiModelProperty(value = "昵称") private String nickname; /** * 脸书id */ @ApiModelProperty(value = "脸书id") private String userId; }Controller层那里的逻辑,次要就是前端挪用facebook登录页面,用户停止facebook登录,登录胜利后会返回一串Json:
{ "accessToken": "密钥", "userID": "facebook用户id", "expiresIn": "", "signedRequest": "", "graphDomain": "", "data_access_expiration_time":"" }那里其实只需要密钥和用户id即可,其他字段按照营业需求停止改动。
拿到密钥后,后端利用HTTPClient停止facebook api 挪用,按照密钥和id拿到用户的相关信息,facebook相关信息返回如下: { "id":"", "name":"", "email":"" }那里能够本身设置facebook返回的用户数据。
后端设想表时更好设想一个用户联系关系表,用于联系关系本身应用的用户信息与facebook用户信息。Service层代码:
/** * 查看用户能否绑定 * * @param userId * @return */ FacebookResult checkUserBinding(FacebookResponse facebookResponse, String userId); /** * 增绑定新用户 * * @param faceBookCustomerLink * @return */ int addFaceBookCustomer(FaceBookCustomerLink faceBookCustomerLink); /** * 按照用户账号查询用户能否有绑定多个账户 */ int queryCustomerByCustomerId(String customerId);实现类:
@Override public FacebookResult checkUserBinding(FacebookResponse facebookResponse, String userId) { if (StringUtils.isEmpty(userId)) { logger.error("facebook login false auth is null"); return new FacebookResult(-1, new Customer(), facebookResponse); } if (faceBookCustomerLinkMapper.queryByUserId(userId) > 1) { logger.error("facebook login false because find two user ...."); return new FacebookResult(-2, new Customer(), facebookResponse); } FaceBookCustomerLink faceBookCustomerLink = faceBookCustomerLinkMapper.queryCustomerByUserId(userId); if (!Objects.isNull(faceBookCustomerLink) && !StringUtils.isEmpty(faceBookCustomerLink.getCustomerId())) { Customer customer = customerService.queryCustomerInfoById(faceBookCustomerLink.getCustomerId()); return new FacebookResult(1, customer, facebookResponse); } return new FacebookResult(0, new Customer(), facebookResponse); } @Override public int addFaceBookCustomer(FaceBookCustomerLink faceBookCustomerLink) { if (Objects.isNull(faceBookCustomerLink)) { logger.error("facebook login fali"); } return faceBookCustomerLinkMapper.addFaceBookCustomerLink(faceBookCustomerLink); } @Override public int queryCustomerByCustomerId(String customerId) { if (StringUtils.isEmpty(customerId)) { logger.error("facebook login fali"); } return faceBookCustomerLinkMapper.queryByCustomerId(customerId); }HttpClientUtil类:
package com.lecshop.util; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.URI; import java.nio.charset.Charset; import java.util.*; public class HttpClientUtil { /** * 调试东西 */ private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); /** * @Title: doGet * @Description: get体例 * @author Mundo */ public static String doGet(String url, Map<String, String> params) { // 返回成果 String result = ""; // 创建HttpClient对象 HttpClient httpClient = HttpClientBuilder.create().build(); HttpGet httpGet = null; try { // 拼接参数,能够用URIBuilder,也能够间接拼接在?传值,拼在url后面,如下--httpGet = new // HttpGet(uri+"?id=123"); URIBuilder uriBuilder = new URIBuilder(url); if (null != params && !params.isEmpty()) { for (Map.Entry<String, String> entry : params.entrySet()) { uriBuilder.addParameter(entry.getKey(), entry.getValue()); // 或者用 // 趁便说一下差别(setParameter会笼盖同名参数的值,addParameter则不会) // uriBuilder.setParameter(entry.getKey(), entry.getValue()); } } URI uri = uriBuilder.build(); // 创建get恳求 httpGet = new HttpGet(uri); logger.info("拜候途径:" + uri); HttpResponse response = httpClient.execute(httpGet); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {// 返回200,恳求胜利 // 成果返回 result = EntityUtils.toString(response.getEntity()); logger.info("恳求胜利!,返回数据:" + result); } else { logger.info("恳求失败!"); } } catch (Exception e) { logger.info("恳求失败!"); logger.error(ExceptionUtils.getStackTrace(e)); } finally { // 释放毗连 if (null != httpGet) { httpGet.releaseConnection(); } } return result; } /** * @Title: doPost * @Description: post恳求 * @param url * @param params * @return * @author Mundo */ public static String doPost(String url, Map<String, String> params) { String result = ""; // 创建httpclient对象 HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost httpPost = new HttpPost(url); try { // 参数键值对 if (null != params && !params.isEmpty()) { List<NameValuePair> pairs = new ArrayList<NameValuePair>(); NameValuePair pair = null; for (String key : params.keySet()) { pair = new BasicNameValuePair(key, params.get(key)); pairs.add(pair); } // 模仿表单 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs); httpPost.setEntity(entity); } HttpResponse response = httpClient.execute(httpPost); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { result = EntityUtils.toString(response.getEntity(), "utf-8"); logger.info("返回数据:>>>" + result); } else { logger.info("恳求失败!,url:" + url); } } catch (Exception e) { logger.error("恳求失败"); logger.error(ExceptionUtils.getStackTrace(e)); e.printStackTrace(); } finally { if (null != httpPost) { // 释放毗连 httpPost.releaseConnection(); } } return result; } /** * @Title: sendJsonStr * @Description: post发送json字符串 * @param url * @param params * @return 返回数据 * @author Mundo */ public static String sendJsonStr(String url, String params) { String result = ""; HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost httpPost = new HttpPost(url); try { httpPost.addHeader("Content-type", "application/json; charset=utf-8"); httpPost.setHeader("Accept", "application/json"); if (StringUtils.isNotBlank(params)) { httpPost.setEntity(new StringEntity(params, Charset.forName("UTF-8"))); } HttpResponse response = httpClient.execute(httpPost); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { result = EntityUtils.toString(response.getEntity()); logger.info("返回数据:" + result); } else { logger.info("恳求失败"); } } catch (IOException e) { logger.error("恳求异常"); logger.error(ExceptionUtils.getStackTrace(e)); } return result; } }到那里facebook的登录的功用根本上就已经完成了,最初,必然要切记,facebook登录时必然不要利用收集东西停止登录拜候,否者根本上号是必然会被封掉的。