点击上方“Java知音”,选择“置顶公众号”

技术文章第一时间送达!

作者:imtech

my.oschina.net/u/4231722/blog/3154805

1、引言

扫码登录这个功能,最早应该是微信的PC端开始搞,虽然有点反人类的功能(不扫码也没别的方式登录),但不得不说还是很酷的。

下面这张图,不管是IM开发者还是普通用户,应该很熟悉:

于是,搞IM产品的老板和产品经理们,从此又多了一个要抛给程序员们的需求——“为什么微信有扫一扫登录,而我们的没有?”。

好吧,每次只要是微信有的功能,IM程序员们想甩锅,难度就有点大了,毕竟老板们都都会想当然认为,微信有的“我”的IM产品里也得有。

既然无法回避,那就只能老老实实搞懂技术原理,然后自已使劲撸吧。

本文将简要的介绍扫码登录功能的技术实现逻辑,并实际结合淘宝、微信的扫码登录功能,学习和研究大厂主流应用的技术实现思路。

2、基本技术原理

2.1 扫码登录功能到底是什么样的?

首先介绍下什么是扫码登录。现在大部分同学手机上都装有微信、qq和淘宝这一类的软件。而这些app都有他们相对应的网页端。为了让用户在使用他们的网页时登录更加方便和安全,使用手机扫一扫就可以登录的服务,就显得自然而然了。

几个主流大厂应用扫码登录时的界面效果如下:

有很多小伙伴可能会感到很神奇,网页上只是显示了个二维码,它怎么就知道是哪个手机扫到了二维码,并且进行登录的呢?而且,登录完成以后,还能直接把用户信息显示给用户,真的是很神奇啊。

2.2 扫码登录功能的完整技术逻辑

1)网页端与服务器的配合逻辑:

接下来就是对于这个服务的详细实现。

首先用户打开网站的登录页面的时候,向浏览器的服务器发送获取登录二维码的请求。服务器收到请求后,随机生成一个uuid,将这个id作为key值存入redis服务器,同时设置一个过期时间,再过期后,用户登录二维码需要进行刷新重新获取。

同时,将这个key值和本公司的验证字符串合在一起,通过二维码生成接口,生成一个二维码的图片(二维码生成,网上有很多现成的接口和源码,这里不再介绍)。然后,将二维码图片和uuid一起返回给用户浏览器。

浏览器拿到二维码和uuid后,会每隔一秒向浏览器发送一次,登录是否成功的请求。请求中携带有uuid作为当前页面的标识符。这里有的同学就会奇怪了,服务器只存了个uuid在redis中作为key值,怎么会有用户的id信息呢?

这里确实会有用户的id信息,这个id信息是由手机服务器存入redis中的。具体请继续阅读“手机端与服务器的配合逻辑”。

2)手机端与服务器的配合逻辑:

话说,浏览器拿到二维码后,将二维码展示到网页上,并给用户一个提示:请掏出您的手机,打开扫一扫进行登录。

用户拿出手机扫描二维码,就可以得到一个验证信息和一个uuid(扫描二维码获取字符串的功能在网上同样有很多demo,这里就不详细介绍了)。

由于手机端已经进行过了登录,在访问手机端的服务器的时候,参数中都会携带一个用户的token,手机端服务器可以从中解析到用户的userId(这里从token中取值而不是手机端直接传userid是为了安全,直接传userid可能会被截获和修改,token是加密的,被修改的风险会小很多)。手机端将解析到的数据和用户token一起作为参数,向服务器发送验证登录请求(这里的服务器是手机服务器,手机端的服务器跟网页端服务器不是同一台服务器)。

服务器收到请求后,首先对比参数中的验证信息,确定是否为用户登录请求接口。如果是,返回一个确认信息给手机端。

手机端收到返回后,将登录确认框显示给用户(防止用户误操作,同时使登录更加人性化)。用户确认是进行的登录操作后,手机再次发送请求。服务器拿到uuId和userId后,将用户的userid作为value值存入redis中以uuid作为key的键值对中。

3)登录成功时的逻辑:

然后,浏览器再次发送请求的时候,浏览器端的服务器就可以得到一个用户Id,并调用登录的方法,生成一个浏览器端的token,再浏览器再次发送请求的时候,将用户信息返回给浏览器,登录成功。这里存储用户id而不是直接存储用户信息是因为,手机端的用户信息,不一定是和浏览器端的用户信息完全一致。

4)详细的技术原理总结如下图所示:

3、淘宝的扫码登录技术实现

本节我们以淘宝的扫码登录为例,来实际研究分析一下淘宝的扫码登录实现逻辑。

登录界面 https://login.taobao.com/member/login.jhtml 传回来的参数为:

然后请求(GET)报文是这样的:

https://qrlogin.taobao.com/qrcodelogin/qrcodeLoginCheck.do?
lgToken=2c3b4d53ef0513787bf4ce711ea5ba53&defaulturl=&_ksTS=1540106757739_2804&callback=jsonp2805

关键的就是lgToken,是网页的唯一ID,当打开了二维码登录的时候,网页在轮询(应该是长轮询long polling)调用接口去请求服务器。扩展:彻底理解cookie,session,token

如果没有扫码,返回的为:

如果扫了的话则会返回:

{"code": "10001","message": "mobile scan QRCode success","success": true}

长时间没有扫码的话,网页端会停止轮询,二维码失效!

当手机端确认登录后,接口返回的是:

{
"code": "10006",
"success": true,"url": "https://login.taobao.com/member/loginByIm.do?uid=cntaobaoxxx&token=ff82fc0d1d395a33d3b38ec5a4981336&time=1530179143250&asker=qrcodelogin&ask_version=1.0.0&defaulturl=https://www.taobao.com&webpas=0b7aed2d43f01825183e4a49c6cae47d1479929926"
}

表示登录成功,当然手机端与服务端在点击"确认登录"之间的交互可能就是这样:网页端生成的lgToken去请求服务端,服务端记住了这个lgToken并认为登录了,当网页端再次轮询请求接口时,就返回真正的登录态Token,网页端此时就可以凭着这个Token来登录了。

详细的技术逻辑如下图所示:

4、微信的扫码登录技术实现

4.1 技术原理流程图

微信的网页版访问地址是:https://wx.qq.com/,有兴趣也可以自行深入研究。

4.2 实际的技术实现逻辑

1)获取唯一的uuid, 以及包含uid信息的二维码:

// 获取uuidgetUUID: function() {vare = t.defer();returnwindow.QRLogin = {},$.ajax({url: i.API_jsLogin,dataType: "script"}).done(function() {200 == window.QRLogin.code ? e.resolve(window.QRLogin.uuid) : e.reject(window.QRLogin.code)}).fail(function() {e.reject()}),e.promise}

2)浏览器轮询服务器,获取扫码状态:

// 查看扫码状态checkLogin: function(e, a) {varn = t.defer(), a = a || 0;returnwindow.code = 0,window.checkLoginPromise = $.ajax({url: i.API_login + "?loginicon=true&uuid="+ e + "&tip="+ a + "&r="+ ~newDate,dataType: "script",timeout: 35e3}).done(function() {newRegExp("/"+ location.host + "/");if(window.redirect_uri && window.redirect_uri.indexOf("/"+ location.host + "/") < 0)returnvoid (location.href = window.redirect_uri);vare = {code: window.code,redirect_uri: window.redirect_uri,userAvatar: window.userAvatar};n.resolve(e)}).fail(function() {n.reject()}),n.promise}

3)根据服务器返回的扫码状态,进行相应的操作:

408 扫码超时:如果手机没有扫码或没有授权登录,服务器会阻塞约25s,然后返回状态码 408 -> 前端继续轮询

400 二维码失效:大约5分钟的时间内不扫码,二维码失效

201 已扫码:如果手机已经扫码,服务器立即返回状态码和用户的基本信息 (window.code=201,window.code.userAvator="…"),-> 前端继续轮询

200 已授权:如果手机点击了确认登录,服务器返回200及token -> 前端停止轮询, 获取到token,重定向到目标页

具体的代码示例如下:

// 根据服务器返回的扫码状态,进行相应的操作functiono(c) {switch(c.code) {case200:t.newLoginPage(c.redirect_uri).then(function(t) {varo = t.match(/<ret>(.*)<\/ret>/), r = t.match(/<script>(.*)<\/script>/), c = t.match(/<skey>(.*)<\/skey>/), s = t.match(/<wxsid>(.*)<\/wxsid>/), l = t.match(/<wxuin>(.*)<\/wxuin>/), d = t.match(/<pass_ticket>(.*)<\/pass_ticket>/), f = t.match(/<message>(.*)<\/message>/), u = t.match(/<redirecturl>(.*)<\/redirecturl>/);returnu ? void (window.location.href = u[1]) : o && "0"!= o[1] ? (alert(f && f[1] || "登录失败"),i.report(i.AUTH_FAIL_COUNT, 1),void location.reload()) : (e.$emit("newLoginPage", {Ret: o && o[1],SKey: c && c[1],Sid: s && s[1],Uin: l && l[1],Passticket: d && d[1],Code: r}),void (a.getCookie("webwx_data_ticket") || n.report(n.ReportType.cookieError, {text: "webwx_data_ticket 票据丢失",cookie: document.cookie})))});break;case201:e.isScan = !0,n.report(n.ReportType.timing, {timing: {scan: Date.now()}}),t.checkLogin(e.uuid).then(o, function(t) {!t && window.checkLoginPromise && (e.isBrokenNetwork = !0)});break;case408:t.checkLogin(e.uuid).then(o, function(t) {!t && window.checkLoginPromise && (e.isBrokenNetwork = !0)});break;case400:case500:case0:vars = a.getCookie("refreshTimes") || 0;s < 5 ? (s++,a.setCookie("refreshTimes", s, .5),document.location.reload()) : e.isNeedRefresh = !0;break;case202:e.isScan = !1,e.isAssociationLogin = !1,a.setCookie("login_frequency", 0, 2),window.checkLoginPromise && (window.checkLoginPromise.abort(),window.checkLoginPromise = null),r()}e.code = c.code,e.userAvatar = c.userAvatar,a.log("get code", c.code)}

4.3 小结

微信网页端扫码登录时,轮询的数据返回采用的是JSONP的形式,这是为了解决跨域问题。如对JSONP不了解的,可以参考:

http://www.52im.net/thread-1038-1-1.html

微信网页端扫码登录时,轮询采用了后台根据扫码情况阻塞前台请求,优化轮询及减少前端的无效轮询。这种技术,请详见:

http://www.52im.net/thread-338-1-1.html

5、本文小结

扫码登录这个功能,现在已经不只出现有IM应用里,各种带有移动端的线上网站也都有了这个功能,所以本文中介绍的技术原理并不局限于只用于实现IM应用中的扫码登录。

另外,为了方便抓取真实的数据进行分析研究,本文中的PC端案例分析是针对的是网页端,但实际上如果你的PC端是富客户端(也就是.exe、.dmg这样的安装版),原理也是一样的,而且还不需要考虑浏览器里的跨域问题等。

阅读本文时,可能涉及到传统的Web端即时通讯技术(为了扫码登录的实时性),比如长轮询等,如果您对这些技术还不太了解的话,可以系统学习一下即时通讯网整理的有关Web端即时通讯方面的资料。

END

Java面试题专栏

【40期】说一下线程池内部工作原理

【39期】Mybatis面试18问,你想知道的都在这里了!

【38期】一份tcp、http面试指南,常考点都给你了

【37期】请你详细说说类加载流程,类加载机制及自定义类加载器

【36期】说说 如何停止一个正在运行的线程?

【35期】谈谈你对Java线程之间通信方式的理解

【34期】谈谈为什么要拆分数据库?有哪些方法?

【33期】分别谈谈联合索引生效和失效的条件

【32期】你知道Redis的字符串是怎么实现的吗?

【31期】了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?应对措施是什么

我知道你 “在看”

阿里面试官:分别说说微信和淘宝扫码登录背后的实现原理?相关推荐

  1. 面试官:说说微信和淘宝扫码登录背后的实现原理?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | my.oschina.net/u/423172 ...

  2. 面试官:聊聊微信和淘宝扫码登录背后的实现原理?

    本文来源: my.oschina.net/u/4231722/blog/3154805 <Java工程师面试突击(第3季)>重磅升级,由原来的70讲增至140讲,内容扩充一倍,升级部分内容 ...

  3. 腾讯面试官:聊聊微信和淘宝扫码登录背后的实现原理?GG了

    作者丨imtech 来源: my.oschina.net/u/4231722/blog/3154805 1.引言 扫码登录这个功能,最早应该是微信的PC端开始搞,虽然有点反人类的功能(不扫码也没别的方 ...

  4. 阿里面试官:分别说说微信和淘宝扫码登录背后的实现原理

    作者:imtech my.oschina.net/u/4231722/blog/3154805 1.引言 扫码登录这个功能,最早应该是微信的PC端开始搞,虽然有点反人类的功能(不扫码也没别的方式登录) ...

  5. 面试官:分别说说微信和淘宝扫码登录背后的实现原理?

    Java面试笔试面经.Java技术每天学习一点 Java面试 关注不迷路 作者:imtech 来源:https://my.oschina.net/u/4231722/blog/3154805 1.引言 ...

  6. 一文详析微信和淘宝扫码登录背后的实现原理!

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 作者:imtech my.oschina.net/u/4231722/blog/3 ...

  7. 微信和淘宝扫码登录背后的实现原理

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2019 超神之路,很肝~ 中文详细注释的开源项目 ...

  8. 分别说说微信和淘宝扫码登录背后的实现原理?

    搬运工,链接在此: https://mp.weixin.qq.com/s/jiU-3879C3Exw_gSJnsbAg

  9. 在系统中集成淘宝扫码登录

    在系统中集成淘宝扫码登录 在系统中集成淘宝扫码登录 申请二维码并存入数据库 在手淘首页搜索框中输入口令,并搜索 点击确认登录后,系统中即可获取到cookie相关信息 在系统中集成淘宝扫码登录 为了在公 ...

  10. Web自动化测试淘宝 扫码登录与客服聊天(Python)

    是这学期的作业,由于淘宝有反爬机制,所以账密登录一定会失败,只能扫码.编写的时候网上资料不多,而且找到的都不可用.我自己编的程序是非常非常简单,非常非常基础的.仅供参考,如果运行不了我也不知道怎么回事 ...

最新文章

  1. 预加载系列一:DNS Prefetching 的正确使用姿势
  2. 20170523xlVBA多条件分类求和一例
  3. 【KVM系列01】KVM简介及安装
  4. zabbix3.2.4监控MySQL5.7.16状态
  5. 关于纠正2009年12月22日的总结的position的absolute.relative用法
  6. SQL Express自动备份
  7. 优秀ppt作品范例_首次公开|锐普的内部PPT配色库
  8. NET sturct值类型
  9. DUTCTF 201x RE20
  10. 读书和不读书有什么区别呢?
  11. Guava cache功能整理
  12. 手机号正则和邮箱正则,常用正则解释
  13. 好的软件测试人员简历是什么样子的?
  14. Java 全栈知识体系
  15. 如何将一个HTML页面嵌套在另一个页面中
  16. Photoshop制作剔透魔法水晶球
  17. 【经验】迅雨田下载测试
  18. java8(三)Stream API
  19. 如何成为一位数据科学家
  20. 【CS231n】十五、深度学习的高效算法和硬件设计_一只神秘的大金毛_新浪博客...

热门文章

  1. 10部程序员必看的纪录片
  2. Tapestry 5 资料
  3. 软件系统介绍文档模板
  4. 各种电子元器件介绍与电路基础作用
  5. ipop映射到ftp服务器,设备作为FTP客户端进行文件传输-IPOP
  6. PHP发卡自动源码,PHP自动化售货发卡网源码
  7. Smart View 11.1.2.5配置共享连接
  8. java session 永不过期_java设置配置session过期时间的方法
  9. 小米路由器安装Linux软件,小米路由器mini安装mixbox教程
  10. 小米路由插件二维码2020_入门级Mesh首选?华来小方Mesh路由深度解析