facebook第三方登录前后端分离

facebook第三方登录三种实现方式:第三种我认为方便简单

 1.js sdk 直接在官网看文档 直接调用他的sdk 官网:https://developers.facebook.com/docs/facebook-login/web

2.自己抒写在服务端验证方式第三方登录:

        2.1首先登录facebook 注册自己应用

        2.2然后配置一些回调地址

        

回调地址自己可以内网穿透实现一下

        2.3其次就是 如下图的 应用编号,和应用密钥一会需要

3.然后就是后端代码

        3.1第一步 重定向跳转授权地址(这个授权地址可以返回给前端,前端控制跳转。前端控制的好处就是,可以将第三方的授权页嵌入到iframe中,适配网站设计)

        3.2写回调接口(就是上边图片)有效OAuth 跳转url(代码中有细致的获取用户信息步骤)

        3.3判断扫码成功

下面看代码

package art.quanse.pixabay.service;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Optional;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import art.quanse.common.Hs;
import art.quanse.pixabay.entity.PixabayUser;
import art.quanse.pixabay.entity.SpringUserToken;
import art.quanse.pixabay.repository.PixabayUserRepository;
import art.quanse.pixabay.repository.SpringUserTokenRepository;
import art.quanse.pixabay.util.HttpHelper;

@RestController
public class RestAuthController {

	@Autowired
	SpringUserTokenRepository springUserTokenRepository;

	@Autowired
	private PixabayUserRepository pixabayUserRepository;

	private ObjectMapper objMapper = new ObjectMapper();

	protected Logger logger = LogManager.getLogger(this);
	// 应用编号
	private static String client_id = "3004389089872349";
	// 应用秘钥
	private static String client_secret = "692a53db3ac80e8d5c3574707e6b9947";
	// 回调地址
	private static String redirect_url = "https://chen2580.mynatapp.cc/pixabay_api/api/facebookLogin/login";
	// 获取tokenUrl
	private static String token_url = "https://graph.facebook.com/v12.0/oauth/access_token";
	// 获取用户信息
	private static String user_url = "https://graph.facebook.com/me";
	// 获取临时口令(code)
	private static String code_url = "https://www.facebook.com/v12.0/dialog/oauth?";
	//判断是否扫码登录成功
	private boolean isLogin=false;
	/**
	 * 
	 * 第一步 重定向到授权地址
	 *
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(value = "/code")
	public static void getAuthorizationCode(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		response.sendRedirect(
				code_url + "client_id=" + client_id + "&redirect_uri=" + redirect_url);
	}
	/**
	 * 第二步回调接口
	 *
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("/callback")
	public Hs<JSONObject> verify(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String code = request.getParameter("code");

		String access_token = request.getParameter("access_token");

		try {
			logger.info("获取到的code:{}", code);
			logger.info("获取到的access_token:{}", access_token);
			String facebookAccessToken = this.getFacebookAccessToken(code);// 1.根据code获取 AccessToken
			boolean verify = this.verify(facebookAccessToken);// 2.判断是否是自己应用授权用户信息
			JSONObject userInfo = this.getUserInfo(facebookAccessToken);//3 根据access_token获取用户信息
			if (verify) {
				isLogin=true;
				//获取到facebook用户信息自己处理下边是我自己的需求
				PixabayUser saveUserMessage = this.saveUserMessage(userInfo);
				if (null != saveUserMessage) {
					SpringUserToken generateToken = generateToken(saveUserMessage.getId());
					userInfo.put("token", generateToken.getToken());
				}

			}
			return new Hs<>(userInfo);
		} catch (Exception e) {
			logger.info("获取到的code{}", code);
		}
		return new Hs<>(9401, "身份验证失败,重新认证");
	}
	/**
	 * 第三步 判断用户是否扫码登录成功
	 *
	 * @return
	 */
	public Hs<Void> isLogin()  {
		if (isLogin) {
			return new Hs<>(200,"登录成功"); //此处可以返回token 此简单处理了
		}
		return new Hs<>(9401,"登录失败");
	}

	/**
	 * 
	 * 
	 * 防止别人拿其他平台的appId授权的token来请求
	 * 
	 * @param access_token
	 * @return
	 * @throws IOException
	 */
	public boolean verify(String access_token) throws IOException {
		StringBuilder stringBuilder = new StringBuilder("https://graph.facebook.com/debug_token?access_token=");
		stringBuilder.append(client_id + "%7C" + client_secret).append("&input_token=").append(access_token);
		String result = HttpHelper.getJson(stringBuilder.toString(), "127.0.0.1", 7890);
		JSONObject readValue = objMapper.readValue(result, JSONObject.class);
		JSONObject jsonObject = readValue.getJSONObject("data");
		try {
			String isValid = jsonObject.getString("is_valid");
			if (null != jsonObject && "true".equals(isValid)) {
				return true;
			}
		} catch (Exception e) {
			logger.info("验证返回的数据为{}", jsonObject);
		}
		return false;
	}

	/**
	 * 保存用户信息
	 * 
	 * @param userMessageBean
	 * @return
	 */
	private PixabayUser saveUserMessage(JSONObject userInfo) {
		PixabayUser pixabayUser = null;
		if (userInfo.getLong("status") == 200) {
			String username = userInfo.getString("name");
			String email = userInfo.getString("email");
			String headPortrait = userInfo.getJSONObject("picture").getJSONObject("data").getString("url");
			pixabayUser = new PixabayUser();
			Optional<PixabayUser> pixAbayUserOptional = pixabayUserRepository.findAllByEmailAddress(email);
			Integer status = 3;
			if (pixAbayUserOptional.isPresent()) {
				pixabayUser = pixAbayUserOptional.get();
				status = pixabayUser.getStatus() != 3 ? pixabayUser.getStatus() : 3;
			}
			pixabayUser.setEmailAddress(email);
			pixabayUser.setHeadPortrait(headPortrait);
			pixabayUser.setUsername(username);
			pixabayUser.setStatus(status);
			PixabayUser savePixabayUser = pixabayUserRepository.save(pixabayUser);
			return savePixabayUser;
		}
		return pixabayUser;
	}

	/**
	 * 生成用户userId新的登录token
	 * 
	 * @param userId
	 * @return
	 */
	public SpringUserToken generateToken(long userId) {
		// 在spring_manager_token表中查找该用户的token
		Optional<SpringUserToken> oldOpt = this.springUserTokenRepository.findByUserId(userId);

		SpringUserToken token = new SpringUserToken();
		token.setUserId(userId);
		String tokenString = this.uuidToken();
		token.setToken(tokenString);
		token.setLastDate(new Date());

		if (oldOpt.isPresent()) {
			SpringUserToken old = oldOpt.get();
			token.setId(old.getId());
		}
		SpringUserToken saved = this.springUserTokenRepository.save(token);
		return saved;
	}

	/**
	 * 给予UUID生成token,不含“-”
	 * 
	 * @return String
	 */
	private String uuidToken() {
		String uuid = UUID.randomUUID().toString();
		return uuid.replace("-", "");
	}

	/**
	 * 根据accessToken获取用户信息
	 * 
	 * @param accessToken
	 * @return
	 * @throws JsonProcessingException
	 */
	private JSONObject getUserInfo(String accessToken) throws JsonProcessingException {
		String responseResult = null;
		JSONObject userInfo = new JSONObject();
		if (null != accessToken) {
			HashMap<String, String> params = new HashMap<String, String>();
			String fields = "id,name,birthday,gender,hometown,email,picture";
			params.put("access_token", accessToken);
			params.put("fields", fields);
			String body = objMapper.writeValueAsString(params);
			logger.info("请求体{}:", body);
			try {
				responseResult = HttpHelper.post(user_url, body, "127.0.0.1", 7890);//设置代理端口请求facebook接口获取用户信息
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (null != responseResult) {
				String result = responseResult;
				userInfo = JSONObject.parseObject(result);
				userInfo.put("status", 200);
				return userInfo;
			}
		}
		userInfo.put("status", 9404);
		userInfo.put("message", "请重新认证");
		return userInfo;
	}

	/**
	 * 根据code获取access_token
	 *
	 * @param code
	 * @return
	 */
	public String getFacebookAccessToken(String code) {
		HashMap<String, String> params = new HashMap<String, String>();
		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 = HttpHelper.post(token_url, objMapper.writeValueAsString(params), "127.0.0.1", 7890);

		} catch (Exception e) {
			e.printStackTrace();
		}
		if (null != responseResult) {
			String result = responseResult;
			JSONObject jsonObject = JSONObject.parseObject(result);
			accessToken = jsonObject.getString("access_token");
		}
		return accessToken;

	}

	public void getCode(HttpServletRequest request, HttpServletResponse response) throws IOException {

		String code_url = "https://www.facebook.com/v13.0/dialog/oauth";
		response.sendRedirect(code_url + "?client_id=" + client_id + "&redirect_uri=" + redirect_url);

	}

}

第三方式通过JustAuth

框架实现,这个框架简单集成好多第三方登录方便简单,默认实现state 三分钟缓存 可以防止csrf。如果自定义缓存实现AuthStateCache接口,可以git看一这个框架 代码思想风格不错对于刚实习的我

引入依赖

<dependency>
            <groupId>me.zhyd.oauth</groupId>
            <artifactId>JustAuth</artifactId>
            <version>1.16.4</version>
</dependency>

创建Request

AuthRequest authRequest = new AuthFacebookRequest(AuthConfig.builder()
                .clientId("Client ID")
                .clientSecret("Client Secret")
                .redirectUri("应用回调地址")
                // 针对国外平台配置代理
                .httpConfig(HttpConfig.builder()
                        .timeout(15000)
                        // host 和 port 请修改为开发环境的参数
                        .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080)))
                        .build())
                .build());

生成授权地址

我们可以直接使用以下方式生成第三方平台的授权链接:

String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());

以上完整代码如下

package art.quanse.demo.controller;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import art.quanse.demo.component.AuthRequestComponent;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;

@RestController
@RequestMapping("/oauth")
public class RestAuthController {

	@Autowired
	AuthRequestComponent authRequestComponent;
	
	/**
	 * 重定向授权地址
	 *
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping("/render")
    public void renderAuth(HttpServletResponse response) throws IOException {
        AuthRequest authRequest = authRequestComponent.getAuthRequest();
        response.sendRedirect(authRequest.authorize(AuthStateUtils.createState()));
    }
	
	/**
	 * 回调接口获取用户信息
	 *
	 * @param callback
	 * @return
	 */
	  @RequestMapping("/callback")
    public Object login(AuthCallback callback) {
		  AuthRequest authRequest = authRequestComponent.getAuthRequest();
        return authRequest.login(callback);
    }
	
}


欢迎大神给与介意,刚实习公司给的任务

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值