微信第三方登录实现原理准备工作

参考微信开放平台:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

准备工作
网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。
在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。

授权流程说明
微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。
微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:

第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
通过code参数加上AppID和AppSecret等,通过API换取access_token;
通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

第一步:请求CODE
第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接:
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。

参数说明

参数 是否必须 说明
appid 是 应用唯一标识
redirect_uri 是 请使用urlEncode对链接进行处理
response_type 是 填code
scope 是 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即
state 否 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
返回说明

用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数
redirect_uri?code=CODE&state=STATE
若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数
redirect_uri?state=STATE


代码如下:

1.前台按钮跳转到后台

 /**网页点击微信登录按钮跳转到此方法***/    @RequestMapping("/wxLogin")public void wxLogin(HttpServletRequest request,HttpServletResponse response){      String redirect_uri = PropertiesUtil.getProperty("wx_redirect_URI");//"https://pre-www.laozicloud.com/third/wxCallBack";String wxAPPID= PropertiesUtil.getProperty("wx_app_ID");//微信开放平台申请的appIDString redirectUrl = request.getParameter("redirectUrl");//授权后的回调地址/***if(StringUtils.isNotBlank(redirectUrl)){//这部分属于业务代码,根据需要添加WebUtil.getSession().setAttribute(SysConstant.URL, redirectUrl);}***///随机产生1-100的随机数long r = Math.round(Math.random()*100);//随机数,增加安全性try{response.setHeader("Access-Control-Allow-Origin", "*");  response.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");  response.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  response.setHeader("X-Powered-By","Jetty");  response.sendRedirect("https://open.weixin.qq.com/connect/qrconnect?appid="+wxAPPID+"&redirect_uri="+URLEncoder.encode(redirect_uri,"utf-8") +"&response_type=code&scope=snsapi_login"+"&state="+r+"#wechat_redirect");}catch(IOException  e) {e.printStackTrace();System.out.println("wxLogin exception "+e.getMessage()); }}

2.用户授权后拿到code和state

    @RequestMapping("/wxCallBack")public ModelAndView wxCallBack(HttpServletRequest request,ModelMap modelMap,ModelAndView modelView,RedirectAttributes attributes,HttpServletResponse response){ //授权成功if(request.getParameter("code")!=null){  String code =  request.getParameter("code");  String accessTokenStr = getAccessToken(code); //根据code获取token和openIdSystem.out.println("accessTokenobj:"+accessTokenStr);if(StringUtils.isNotBlank(accessTokenStr){  JSONObject returnObj = JSONObject.parseObject(accessTokenStr);  if (returnObj!=null){  String access_token = returnObj.getString("access_token");  String openId = returnObj.getString("openid");  System.out.println("access_token:"+access_token+"   openId:"+openId);String userInfo = getUserInfo(access_token,openId); //根据token和openId获取用户信息System.out.println("userinfo:"+userInfo); /****获取到用户信息后处理页面代码***/if(StringUtils.isNotBlank(userInfo)) {JSONObject jsonObject = JSONObject.parseObject(userInfo);String avatar = jsonObject.getString("headimgurl");String nickname =jsonObject.getString("nickname");String openid =jsonObject.getString("unionid");ThirdUserVO thirdUser = new ThirdUserVO();thirdUser.setAvatar(avatar);thirdUser.setNickName(nickname);thirdUser.setOpenId(openid);        thirdUser.setRegisterMethod("weixin");modelView=getModelAndView( modelView, thirdUser, request,  modelMap, attributes,response);return modelView;}else {modelMap.put("errorMsgKey", "第三方登录qq出错了");return new ModelAndView("redirect:/login", new ModelMap()); }}  }  }else {//取消授权System.out.println("用户取消了授权:"); return new ModelAndView("redirect:/login", new ModelMap());}return new ModelAndView("redirect:/login", new ModelMap());}

3.根据code获取token和openId

 /** * 获得code后获取access_token { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } * @param code */  public String getAccessToken(String code){  // https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code  try{  String wxAPPID = PropertiesUtil.getProperty("wx_app_ID");String wxSECRET = PropertiesUtil.getProperty("wx_secret");String url = "https://api.weixin.qq.com/sns/oauth2/access_token";  String param = "appid="+wxAPPID+"&secret="+wxSECRET+"&code="+code+"&grant_type=authorization_code";  return sendGet(url,param);  }catch (Exception e){  e.printStackTrace();  }  return null;  }  
 /** * 发送GET请求 * @param url * @param param * @return */  public static String sendGet(String url, String param) {  String result = "";  BufferedReader in = null;  try {  String urlNameString = url + "?" + param;  URL realUrl = new URL(urlNameString);  URLConnection connection = realUrl.openConnection();  connection.setRequestProperty("accept", "*/*");  connection.setRequestProperty("connection", "Keep-Alive");  connection.setRequestProperty("user-agent",  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");  connection.connect();  Map<String, List<String>> map = connection.getHeaderFields();  for (String key : map.keySet()) {  System.out.println(key + "--->" + map.get(key));  }  in = new BufferedReader(new InputStreamReader(  connection.getInputStream()));  String line;  while ((line = in.readLine()) != null) {  result += line;  }  } catch (Exception e) {  e.printStackTrace();  }  finally {  try {  if (in != null) {  in.close();  }  } catch (Exception e2) {  e2.printStackTrace();  }  }  return result;  }  

4.根据token和openId获取用户信息

    public String getUserInfo(String access_token,String openId){  return sendGet("https://api.weixin.qq.com/sns/userinfo","access_token="+access_token+"&openid="+openId);  }  

---------------微信登录的到此结束,以下是qq登录的---------------

在QQ互联参考文档:https://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0

1.点击QQ按钮后跳转到此方法

 @RequestMapping(value="/qqlogin")public void qqlogin(HttpServletRequest request,HttpServletResponse response){String redirectUrl = request.getParameter("redirectUrl");if(StringUtils.isNotBlank(redirectUrl)){WebUtil.getSession().setAttribute(SysConstant.URL, redirectUrl);}response.setContentType("text/html;charset=utf-8");String state = UUID.randomUUID().toString().replace("-", "").toUpperCase();try {response.sendRedirect(String.format(AUTHORIZE_URL, PropertiesUtil.getProperty("qq_app_ID"),URLEncoder.encode(PropertiesUtil.getProperty("qq_redirect_URI"), "UTF-8"),state,"get_user_info"));} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

2.授权后回调的方法

    @RequestMapping(value="/qqloginCallBack")public ModelAndView qqloginCallBack(ModelAndView modelView,HttpServletRequest request,ModelMap modelMap,RedirectAttributes attributes,HttpServletResponse response) throws IOException {
//        modelView=getModelAndView( modelView, new ThirdUserVO(), request,  modelMap, attributes);String code = request.getParameter("code");if(StringUtils.isEmpty(code)) {return initErrorMsg(modelView);}System.out.println("code:"+code);String access_token = getAccessToken( PropertiesUtil.getProperty("qq_app_ID"), PropertiesUtil.getProperty("qq_app_KEY") , code, PropertiesUtil.getProperty("qq_redirect_URI"));if("error".equals(access_token)) {return initErrorMsg(modelView);} String openid = getOpenId(access_token);System.out.println("openid:"+openid);String content = HttpClientUtil.get(getGetUserInfoUrl(access_token,PropertiesUtil.getProperty("qq_app_ID"),openid), null);System.out.println("content:"+content);if(StringUtils.isNotBlank(content)) {JSONObject jsonObject = JSONObject.parseObject(content);ThirdUserVO thirdUser = new ThirdUserVO();thirdUser.setAvatar(jsonObject.getString("figureurl_qq_1"));thirdUser.setNickName(jsonObject.getString("nickname"));thirdUser.setOpenId(openid);        thirdUser.setRegisterMethod("qq");modelView=getModelAndView( modelView, thirdUser, request,  modelMap, attributes,response);return modelView;}else {
//            modelMap.put("errorMsgKey", "第三方登录qq出错了");
//            return new ModelAndView("redirect:/login", new ModelMap()); return initErrorMsg(modelView);}}

完整代码:

链接: https://pan.baidu.com/s/1cqIgYUThZ3YrYjP-kQerDA 提取码: 9b4u

有问题欢迎留言探讨!

PC端微信QQ第三方登录相关推荐

  1. 细说pc端微信扫码登录

    最近做了一个pc端微信扫码登录和微信付款的功能,一个比较常见的问题是在移动端使用微信扫码操作完毕后,pc端如何实时响应的问题.这里细说一下登录的实现流程,付款方面暂时还没找到比较好的实现方法,只能暂时 ...

  2. 前端PC端微信扫码登录

    PC端微信扫码登录 一.微信开放平台 1.创建网站应用 2.设置回调域名 二.代码 1.在index.html页面引入http://res.wx.qq.com/connect/zh_CN/htmled ...

  3. Springboot 实现 PC端 微信扫码登录

    依赖 <!-- httpclient--><dependency><groupId>org.apache.httpcomponents</groupId> ...

  4. 微信QQ第三方登录分享和支付宝微信支付

    登录是使用的是友盟第三方登录:APPID 和APPKEY都是成对出现的,改一个都要改不然出错. QQ第三方登录: APPID ,APPKEY: 微信第三方登录:WEIXINID, WEIXINKEY ...

  5. 微信,qq第三方登录链接

    wap的qq(QQ互联):https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=716027609 &pt_3rd_aid=200002 & ...

  6. PC端微信可自动登录,终于不用手机扫码了

    部分用户的 PC 版本 微信已经支持自动登录, 即不借助手机扫码 就可以独立登录 PC 版微信. 该功能目前仍处于灰度测试中. 图片 自动登录功能.自动登录功能需要在手机微信「已登录设备」页面,或者扫 ...

  7. 踩坑!android端集成QQ第三方登录

    有时候在想,自己怎么能这么懒,几篇早就想写的博客,一直拖到一两个月后才着手开始写,说实话都有点忘记了,但还是记录一下吧,兴许以后用的到呢~ 回归正题,这次来记录一下我集成QQ三方登录的过程吧(Ps:a ...

  8. PC端 微信扫码登录

    1.当前页面打开微信二维码页面 window.location = 'https://open.weixin.qq.com/connect/qrconnect?' + 'scope=' + this. ...

  9. vue PC端微信扫码登录

    我用的element,要是在弹窗里面使用,还是用自定义弹窗比较好,据说用官方的el-dialog会出不来.上代码: 在index.html页面里面引入对应的脚本 <script src=&quo ...

最新文章

  1. 程序员学霸!top2大学毕业!不到30岁第一次升P9失败!挫折感极强,怀疑人生?网友:没升P7的我,不要面子的吗??...
  2. numpy meshgrid用法
  3. Zabbix JVM 安装
  4. idea git 在文件上点了revert怎么复原_在 IntelliJ IDEA 中使用 Git,太方便了
  5. 【专升本计算机】甘肃省专升本计算机基础--判断题--汇编(737道带答案)
  6. QQ各等级所需在线时长明细表
  7. JavaScript入门笔记
  8. 【CSWS2014 Main Conference】Some Posters
  9. Vue遍历对象,数组,v-if、v-if-else、v-else
  10. juniper *** LT2P
  11. Socket编程模式理解与对比
  12. android java 图像显示不出来_Java-Android Studio无法在图像视图中显示图像
  13. IDEA maven process terminated
  14. java定时器每天执行一次_定时器-每天23:00执行一次
  15. 用计算机控制单片机的程序编写,单片机程序编写步骤
  16. 智能运维 | 我们不一样!告诉你百度云如何做智能流量异常检测
  17. 36岁大数据人被中台问倒,没点架构思维,连面试都过不了?
  18. ​做让用户安心合规的智能家居产品——智能家庭用户个人信息保护方案
  19. 【比赛回顾】广工2020程序设计初赛B-秋夜easy
  20. 01背包与完全背包(动态规划)(01背包)

热门文章

  1. shell 概述 shell 入门基础必知
  2. 计算机综合症要拍片,害怕去医院拍片,辐射太可怕?关于影像学检查的真相在这里...
  3. 前端导出word(包含图表)
  4. 【转】OCV、AOCV、POCV、LVF都有什么作用?
  5. 迷你辦公室 迷你寫字樓 商務寫字樓 商務中心
  6. 长沙VR丨云图科技VR模拟灾难演习!
  7. 2017-2020年人工智能公司死亡名单
  8. 【 ASUS ac-1200刷openwrt】
  9. CURL 中文乱码解决方法
  10. Windows 常用系统检测命令