0


facebook第三方登录前后端分离

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

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

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

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

    2.2然后配置一些回调地址

    ![](https://img-blog.csdnimg.cn/288db25e5ce64765b7870298951afc6e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6Ieq5L-h77yM6KOF6L295piO5aSp,size_20,color_FFFFFF,t_70,g_se,x_16)

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

    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);
    }
    
}

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


本文转载自: https://blog.csdn.net/weixin_52455398/article/details/123029303
版权归原作者 自信,装载明天 所有, 如有侵权,请联系我们删除。

“facebook第三方登录前后端分离”的评论:

还没有评论