ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第三方登陆--QQ登陆

2020-06-26 11:02:15  阅读:329  来源: 互联网

标签:QQ code top yangbuyi params 登陆 put import 第三方


从零玩转第三方QQ登陆

在真正开始对接之前,我们先来聊一聊后台的方案设计。既然是对接第三方登录,那就免不了如何将用户信息保存。首先需要明确一点的是,用户在第三方登录成功之后,
我们能拿到的仅仅是一个代表用户唯一身份的ID(微博是真实uid,QQ是加密的openID)以及用来识别身份的accessToken,当然还有昵称、头像、性别等有限资料,
对接第三方登录的关键就是如何确定用户是合法登录,如果确定这次登录的和上次登录的是同一个人并且不是假冒的。其实这个并不用我们特别操心,就以微博登录为例,
用户登录成功之后会回调一个code给我们,然后我们再拿code去微博那换取 accessToken ,如果这个code是用户乱填的,那这一关肯定过不了,所以,前面的担心有点多余,哈哈。

1. 认识Oauth2.0

现在很多网站都要不管是为了引流也好,为了用户方便也好一般都有第三方账号登陆的需求,今天以QQ登陆为例,来实现一个最简单的第三方登陆。
目前主流的第三方登录都是依赖的Oauth2.0实现的,最常见的就是在各种中小型网站或者App中的QQ登录,微信登录等等。所以我建议想要学习和实现第三方登录同学去了解下这个协议。

1.2 必须要域名并且进行备案

比如我的域名: https://yangbuyi.top/
因为腾讯有一个域名认证机制啥的。。。。。。

2.实名认证

QQ登录我们对接的是QQ互联,地址:https://connect.qq.com ,首先需要注册成为开发者并实名认证,需要手持身份证照片,具体就不讲了。

2.1、进行申请开发者身份

2.2 创建应用

进入应用管理页面创建应用,根据实际需要是创建网站应用还是移动应用,我这里是网站应用:

提交成功完步后等待客服审核即可

2.3. QQ登陆流程

2.4. 请求参数

3.前台准备

/** * 封装一个居中打开新窗口的方法 */ function openWindow(url, width, height) { width = width || 600; height = height || 400; var left = (window.screen.width - width) / 2; var top = (window.screen.height - height) / 2; var win =window.open(url, "_blank", "toolbar=yes, location=yes, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=no, copyhistory=yes, left=" + left + ", top=" + top + ", width=" + width + ", height=" + height); console.log(win) }

3.1 使用 随便点击按钮进行调用这个 qq函数

3.2 点击访问后端 登陆方法

4. 后端实现

package top.yangbuyi.system.controller;

import com.google.gson.Gson;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.yangbuyi.system.common.ActiveUser;
import top.yangbuyi.system.common.Constant;
import top.yangbuyi.system.common.HttpsUtils;
import top.yangbuyi.system.common.WebUtils;
import top.yangbuyi.system.config.QQ.OAuthProperties;
import top.yangbuyi.system.config.QQ.vo.QQDTO;
import top.yangbuyi.system.config.QQ.vo.QQOpenidDTO;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * description:  杨不易网站 :www.yangbuyi.top
 * program:  yangbuyi-erp-2020
 * ClassName:  QQController
 * create:  2020-06-24 17:17
 *
 * @author: yangbuyi
 * @since: JDK1.8
 **/

@RestController
@RequestMapping("api")
public class QQController {
      
      @Autowired
      private OAuthProperties oauth;
      private static final Logger logger = LoggerFactory.getLogger(QQController.class);
      
      /**
       * 调用QQ登陆接口
       *
       * @param response
       */
      @GetMapping("/login/oauth")
      public String loginQQ(HttpServletResponse response) {
            /**
             * 重定向
             */
//                  response.sendRedirect();//授权模式,授权码模式
            
            System.out.println(
                  oauth.getQQ().getCode_callback_uri() + //获取code码地址
                        "?client_id=" + oauth.getQQ().getClient_id()//appid
                        + "&state=" + UUID.randomUUID() + //这个说是防攻击的,就给个随机uuid吧
                        "&redirect_uri=" + oauth.getQQ().getRedirect_uri() +//这个很重要,这个是回调地址,即就收腾讯返回的code码
                        "&response_type=code"
            );

            return oauth.getQQ().getCode_callback_uri() + //获取code码地址
                  "?client_id=" + oauth.getQQ().getClient_id()//appid
                  + "&state=" + UUID.randomUUID() + //这个说是防攻击的,就给个随机uuid吧
                  "&redirect_uri=" + oauth.getQQ().getRedirect_uri() +//这个很重要,这个是回调地址,即就收腾讯返回的code码
                  "&response_type=code";

            
      }
      
      
      //接收回调地址带过来的code码
      @GetMapping("/oauth2")
      public String authorizeQQ(Map msg, String code, HttpServletResponse response) {
            HashMap params = new HashMap<>();
            params.put("code", code);
            params.put("grant_type", "authorization_code");
            params.put("redirect_uri", oauth.getQQ().getRedirect_uri());
            params.put("client_id", oauth.getQQ().getClient_id());
            params.put("client_secret", oauth.getQQ().getClient_secret());
            //获取access_token如:access_token=9724892714FDF1E3ED5A4C6D074AF9CB&expires_in=7776000&refresh_token=9E0DE422742ACCAB629A54B3BFEC61FF
            String result = HttpsUtils.doGet(oauth.getQQ().getAccess_token_callback_uri(), params);
            //对拿到的数据进行切割字符串
            String[] strings = result.split("&");
            //切割好后放进map
            Map reulsts = new HashMap<>();
            for (String str : strings) {
                  String[] split = str.split("=");
                  if (split.length > 1) {
                        reulsts.put(split[0], split[1]);
                  }
            }
            //到这里access_token已经处理好了
            //下一步获取openid,只有拿到openid才能拿到用户信息
            String openidContent = HttpsUtils.doGet(oauth.getQQ().getOpenid_callback_uri() + "?access_token=" + reulsts.get("access_token"));
            //接下来对openid进行处理
            //截取需要的那部分json字符串
            String openid = openidContent.substring(openidContent.indexOf("{"), openidContent.indexOf("}") + 1);
            Gson gson = new Gson();
            //将返回的openid转换成DTO
            QQOpenidDTO qqOpenidDTO = gson.fromJson(openid, QQOpenidDTO.class);
            
            //接下来说说获取用户信息部分
            //登陆的时候去数据库查询用户数据对于openid是存在,如果存在的话,就不用拿openid获取用户信息了,而是直接从数据库拿用户数据直接认证用户,
            // 否则就拿openid去腾讯服务器获取用户信息,并存入数据库,再去认证用户
            //下面关于怎么获取用户信息,并登陆
            params.clear();
            params.put("access_token", reulsts.get("access_token"));//设置access_token
            params.put("openid", qqOpenidDTO.getOpenid());//设置openid
            params.put("oauth_consumer_key", qqOpenidDTO.getClient_id());//设置appid
            //获取用户信息
            String userInfo = HttpsUtils.doGet(oauth.getQQ().getUser_info_callback_uri(), params);
            QQDTO qqDTO = gson.fromJson(userInfo, QQDTO.class);
            //这里拿用户昵称,作为用户名,openid作为密码(正常情况下,在开发时候用openid作为用户名,再自己定义个密码就可以了)
            try {
                  System.out.println("用户信息:" + userInfo);
                  System.out.println(qqDTO);
                  // 获取主体
                  Subject subject = SecurityUtils.getSubject();
//                  SecurityUtils.getSubject().login(new UsernamePasswordToken(qqOpenidDTO.getOpenid(), Constant.DEFAULT_PWD));
                  System.out.println(qqOpenidDTO.getOpenid());
                  subject.login(new UsernamePasswordToken(qqDTO.getNickname(), Constant.DEFAULT_PWD));
                  
                  String token = subject.getSession().getId().toString();
                  ActiveUser active = (ActiveUser) subject.getPrincipal();
                  params.put("token", token);
                  params.put("code", 200);
                  params.put("permissions", active.getPermissions());
                  params.put("username", active.getUser().getName());
                  params.put("usertype", active.getUser().getType());
                  System.out.println("Shiro认证成功");
            } catch (Exception e) {
                  msg.put("msg", "第三方登陆失败,请联系管理!");
                  logger.error(e.getMessage());
                  System.out.println("Shiro认证失败");
//                  return new ResultObj(-1, "login.html");
//                  return "redirect:https://www.yangbuyi.top/login.html";
                  WebUtils.getHttpSession().setAttribute("params", params);
                  return "/login.html";
            }
//            return "redirect:" + "https://www.yangbuyi.top/"
//            params
            
            
            WebUtils.getHttpSession().setAttribute("params", params);
//            return "redirect:https://www.yangbuyi.top/index.html";
           // return "getParams";
            return "/index.html";
      }
      
      /**
       * 获取参数
       *
       * @return
       */
      @RequestMapping("getParams")
      public Object getParams() {
            System.out.println(WebUtils.getHttpSession().getAttribute("params"));
            return WebUtils.getHttpSession().getAttribute("params");
      }
      
      
}

标签:QQ,code,top,yangbuyi,params,登陆,put,import,第三方
来源: https://www.cnblogs.com/Yangbuyi/p/13194007.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有