微信扫码登录技术实现的简单思考

微信扫码登录是经常用到的的骚操作,但是,其实现的思路是怎样的,可能很多人都没有去思考过。记得曾经在一次面试当中,面试官就曾问过微信扫码登录的实现思路,这次,以微信读书网页版扫码登录为例子,聊聊我对微信扫码登录技术实现思路一些思考。

以谷歌浏览器来做本次分析,打开F12,准备随时观察http连接状况。

接下来用谷歌浏览器打开网页版微信读书,点击登录,会弹出一个二维码:

image

可以看到,在二维码弹出来的时候,前端调用了后端两个接口,一个是getuid(),一个是getinfo(),这里面涉及到哪些逻辑实现呢?

image

稍微思考一下,其实很好理解,每个随机生成的二维码,其实都是一个uuid码,也就是说,在点击登录的时候,会执行一个getuid()方法,去调用后端API:web/login/getuid,然后返回一个随机生成的uuid码。当这个uuid码返回到前端上时,就会以二维码的形式展示。根据uuid如何生成二维码,我后面再写一篇小白文来分析下。

在谷歌浏览器F12调出的控制台页面,点击getuid(),在右边栏的Preview框里,可看到该方法返回一个随机生成的uuid:38e673a9-5bd3-4f0c-ba2f-62ab376372a9

image

返回uuid的同时,还调用了另一个getinfo()方法——可见,这应该是getuid调用成功后的回调方法,也就是当getuid()执行成功后,在得到一个uid时,就立马调用getinfo()方法,同时将生成的uid当做参数传给getinfo(),让其去访问后端API。

image

当没有用手机微信进行扫码操作时,会看到getinfo()一直没有返回值,这时,它传给后端的uuid正在做轮询查询操作,在某段时间内,若没有轮询成功,就会断开连接,接口调用失败。

image

到这里,可以简单归纳下网页版微信登录页面生成二维码的流程,即,在点击登录按钮时,代码层面会执行getuid()方法去调用后端API接口,即“https://weread.qq.com/web/login/getuid”,后台将随机生成一个唯一uid返回。前端得到正常返回状态后,就会将参数传给getuid的回调方法getinfo({"uid":"38e673a9-5bd3-4f0c-ba2f-62ab376372a9"}),该getinfo方法会将uid参数传给后端API接口“https://weread.qq.com/web/login/getinfo”,这时,后端内部将一直做轮询拿uid去redis查询,若能查询成功,即登录成功,反之,则连接超时失败。

下面用两段伪代码来说明下大概代码逻辑:

一.前端React获取uuid并回调给getinfo()伪代码:

  1 export const getuid=(params={},queue='getuid')=>dispatch=>{
  2     http.post({
  3         url:'https://weread.qq.com/web/login/getuid',
  4         params:params,  5         queue:queue,1)">  6         callback:(res)=>{
  7             //getuid方法执行成功,返回{uid: "38e673a9-5bd3-4f0c-ba2f-62ab376372a9"},
//回调执行getinfo()
8 dispatch(getinfo({uid:res.uid})) 9 } 10 }); 11 } 12 13 export const getinfo=(params={},queue='getinfo')=>dispatch=>{ 14 http.get({ 15 url:'https://weread.qq.com/web/login/getinfo',1)"> 16 params:params,1)"> 17 queue:queue,1)"> 18 callback:(res)=>{ 19 //若登录成功,应该重定向到已登录状态的主页 20 } 21 }); 22 }

 

二.后端API接口/web/login/getinfo伪代码:

  1 public String getinfo(String uid){
  2     ......
  3         //循环查询uid在redis里是否存在值
  4         while(true){
  5             String user=redisTemplate.opsForValue().get(uid);
  6             if(user!=null){
  7                 return user;
  8             }
 10     ......
 11 }

 

用一个时序图来简单表示这个过程:

image

那么,什么时候才能通过uid去redis查询才能得到返回值呢?

这时候,就要说到扫码阶段了

当getinfo(String uid)接口在轮询查询redis是否有key为uid的值时,用户拿出手机,在二维码有效时间内,用微信扫一扫进行扫码操作,这时,手机上就会出现该页面展示:

image-20210309231421142

若点击登录,网页版微信读书就会刷新,进入到已登录状态的首页。

这个过程很好理解,即在扫码后,手机端会从二维码中获取到uid,这时,若点登录,就会将uid与微信用户信息一块包装成json格式post提交给后端,然后在后端接口中,将以uid:user的key-value形式set插入到redis数据库。这时,另一边正在以uid当做key值轮询去redis是否有值的getinfo(String uid)方法,通过类似redisTemplate.opsForValue().get(uid)的方式,正好就能通过uid把刚插入redis的user信息查询出来,最后返回给PC端的微信读书前端,即登录成功。

最后,完整的流程可以时序图这样表示:

 

image

PC端微信读书登录成功的时候,页面重新做了刷新,应该是在后台做了接口重定向,具体如何重定向,感兴趣的朋友可以自行思考研究,微信扫码登录大体上就是这个思路,但细节方面应该会有更多相关校验在里面。

这里主要是分析下它的整体实现思路。

值得提一点是,PC端微信读书前端其实做了反调试,但没关系,它这个反调试的做法很容易破解,可参考我的做法,即打开谷歌浏览器,按F12,调出控制台,把这个图标点亮,就可以关闭微信读书前端自带的反调试设置了。

image

原文地址:https://www.cnblogs.com/zhujiqian

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 连接 连接池产生原因 连接池实现原理 小结 TEMPERANCE:Eat not to dullness;drink not to elevation.节制
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体现在所写的每一行代码上。-- 毕玄 1. 命名风格 【书摘】类名用 UpperCamelC
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个人在用”。哪怕只是throw了一个新的Exception。哈哈,这是我犯的错误。一、接口和抽象类类,即一个对象。先抽象类,就是抽象出类的基础部分,即抽象基类(抽象类)。官方定义让人费解,但是记忆方法是也不错的 —包含抽象方法的类叫做抽象类。接口
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket一、引子文件,作为常见的数据源。关于操作文件的字节流就是 —FileInputStream&FileOutputStream。
作者:泥沙砖瓦浆木匠网站:http://blog.csdn.net/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_Aonqz
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程与多线程 线程是什么? 线程(Thread)是一个对象(Object)。用来干什么?Java 线程(也称 JVM 线程)是 Java 进程内允许多个同时进行的任务。该进程内并发的任务成为线程(Thread),一个进程里至少一个线程。 Ja
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket在面向对象编程中,编程人员应该在意“资源”。比如?1String hello = "hello"; 在代码中,我们
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 《程序兵法:Java String 源码的排序算法(一)》 文章工程:* JDK 1.8* 工程名:algorithm-core-le
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 一、父子类变量名相同会咋样? 有个小故事,今天群里面有个人问下面如图输出什么? 我回答:60。但这是错的,答案结果是 40 。我知错能改,然后说了下父子类变
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统挺适合开发者进行写代码,最近碰到了一个问题,问题是如何在 macOS 根目录创建文件夹。不同的 ma
作者:李强强上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算。这一讲,泥瓦匠带你走进Java中的进制详解。一、引子在Java世界里,99%的工作都是处理这高层。那么二进制,字节码这些会在哪里用到呢?自问自答:在跨平台的时候,就凸显神功了。比如说文件读写,数据通信,还
1 线程中断 1.1 什么是线程中断? 线程中断是线程的标志位属性。而不是真正终止线程,和线程的状态无关。线程中断过程表示一个运行中的线程,通过其他线程调用了该线程的 方法,使得该线程中断标志位属性改变。 深入思考下,线程中断不是去中断了线程,恰恰是用来通知该线程应该被中断了。具体是一个标志位属性,
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want需求 项目在设计表的时候,要处理并发多的一些数据,类似订单号不能重复,要保持唯一。原本以为来个时间戳,精确到毫秒应该不错了。后来觉得是错了,测试环境下很多一
纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 加微信:bysocket01
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want.文章Points:1、介绍RESTful架构风格2、Spring配置CXF3、三层初设计,实现WebService接口层4、撰写HTTPClient 客户
Writer :BYSocket(泥沙砖瓦浆木匠)什么是回调?今天傻傻地截了张图问了下,然后被陈大牛回答道“就一个回调…”。此时千万个草泥马飞奔而过(逃哈哈,看着源码,享受着这种回调在代码上的作用,真是美哉。不妨总结总结。一、什么是回调回调,回调。要先有调用,才有调用者和被调用者之间的回调。所以在百
Writer :BYSocket(泥沙砖瓦浆木匠)一、什么大小端?大小端在计算机业界,Endian表示数据在存储器中的存放顺序。百度百科如下叙述之:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加
What is a programming language? Before introducing compilation and decompilation, let's briefly introduce the Programming Language. Programming la
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket泥瓦匠喜欢Java,文章总是扯扯Java。 I/O 基础,就是二进制,也就是Bit。一、Bit与二进制什么是Bit(位)呢?位是CPU
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocket一、前言 泥瓦匠最近被项目搞的天昏地暗。发现有些要给自己一些目标,关于技术的目标:专注很重要。专注Java 基础 + H5(学习) 其他操作系统,算法,数据结构当成课外书博览。有时候,就是那样你越是专注方面越