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

参考微信开放平台: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. pip国内常用源及配置方式
  2. 使用java代码发送电子邮件
  3. .bak 服务器备份文件,如何从SQL Server Management Studio中的多个备份(bak)文件还原数据库...
  4. spring中容器启动过程中初始化资源使用方法
  5. Spring_AOP架构介绍与源码分析(含事务深度分析)
  6. python旋转坐标系_python实现一个点绕另一个点旋转后的坐标
  7. react中的render-props模式
  8. 计算机专业能进教育局吗,教育局一般招什么专业
  9. opc客户端_通过OPC接口将TOP Server与Proficy iFix配合使用(上)
  10. android是j2me的一个实现吗,j2me与android的区别
  11. 联想Win7 SP1 32位/64位OEM系统[官方原版]
  12. 《JAVA常用算法手册》学习笔记(一)
  13. yota3无第三方recovery root方法
  14. uniapp调起打印机(调起第三方打印软件)适用app,将页面生成图片打印的两种方式
  15. 转回到Edison上开发
  16. 1949. 坚定的友谊
  17. 电机振动噪声(NVH)气隙磁场推导
  18. 解决 java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x82\xF0\x9F...'
  19. 关于灾备的重要性解读
  20. 详解redis5.x版本

热门文章

  1. 档案丢失社保难办是谁的错?
  2. 使用js将HTML页面转成pdf
  3. oracle 语句的妙用例子
  4. 基于tableau进行APP高频访问场景数据分析
  5. 《人月神话》(The Mythical Man-Month)5画蛇添足(The Second-System Effect)
  6. AI绘画提示词创作指南:DALL·E 2、Midjourney和 Stable Diffusion最全大比拼
  7. java达达租车接口_java达达租车系统,初学者,希望大家能给些批评建议,共同学习...
  8. 1688API接口:item_search_img - 按图搜索1688商品(拍立淘
  9. html5报名页面设计
  10. MySQL和SQLite根据生日算年龄