写点什么

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

用户头像
朱季谦
关注
发布于: 2021 年 03 月 26 日

原创/朱季谦


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

以谷歌浏览器来做本次分析,打开 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, 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', 16 params:params, 17 queue:queue, 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             }  9         } 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


发布于: 2021 年 03 月 26 日阅读数: 33
用户头像

朱季谦

关注

一个以编程为生的荒诞小说家 2018.06.29 加入

汤圆创作APP签约作者; 简书优秀认证作者; Java后端程序员; PMP认证人员; 学生时代著有《黑色玫瑰》一书已上架微信读书APP;

评论

发布
暂无评论
微信扫码登录技术实现的简单思考