文章目录
大家肯定都知道什么是第三方登陆,以登陆CSDN来说,假设我们选择了以QQ进行认证登陆则当我们点击小企鹅图标时,会进入到一个QQ的授权页面,只要你用手机QQ进行扫码或者在QQ在线时点击QQ头像、没在线时输入QQ账号和密码就可以登陆到我们自己的CSDN了。
在这个过程中当我们点击小企鹅图标时
- CSDN将我们引导到了一个QQ的授权页面
- 在QQ授权页面里我们要进行扫码或输入QQ号和密码 —> 总之就是进行了一下授权
- 在QQ授权页面认证之后就可以登陆到我们的CSDN了
1 可以很容易想到的点
再进一步细细地推敲一下上诉整个过程,我们应该可以想到如下几点:
(1)在QQ进行了授权之后,CSDN肯定是从QQ那里拿到了什么。
假如说CSDN后端用的是spring-security的话,结合前面讲的手机验证码登陆和用户名/密码登陆,其实就可以很自然地想到,CSDN的服务端很可能就是通过从QQ那里拿到的东西,进行了一系列认证,如果认证通过后则将认证成功的信息放入到SecurityContext中,这样就完成了登陆CSDN的操作了。
那问题又来了,在上诉过程中CSDN到底从QQ拿到了什么信息呢?
—> QQ的用户名或QQ号+密码信息吗 其实用脚趾头想想也不可能!!!这要是给了,那我们直接开发个第三方登陆功能,那就可以直接获取别人的QQ密码了,那还了得!!!实际上,CSDN从QQ只是拿到了我们QQ账号的用户基本信息,比如说QQ号、QQ头像、QQ用户名等,QQ密码等关键信息肯定是获取不到的。
(2)CSDN从QQ那里拿到的内容肯定与CSDN的用户信息之间有一个对应关系
其实这很容易理解,就像前面讲的手机短信登陆,虽然你短信验证码可能输入对了,但是肯定还得去数据库里看一看,你这个手机号到底有没有在我们系统里注册过,如果有的话,你才能被认定为登陆成功。
同理,CSDN虽然从QQ拿到了QQ号、QQ用户名等信息,肯定得拿着这些信息去我们数据库里看一下,这个QQ号到底与哪个CSDN账户进行关联,不然怎么知道是哪个CSDN用户正在进行登陆呢?
(3)CSDN肯定和QQ建立了某种关系,或拿到了什么特权
为什么这么说呢?首先用户一点击小企鹅,我们就被引导到了一个QQ的授权页面,但如果两者没建立关系的话人家QQ凭什么让你访问人家的授权页面???就算让你访问,又怎么知道是CSDN的用户正在进行授权登陆呢???
小结:
上面说了那么多,其实就是想说明,从常理来看我们是可以猜出第三方登陆的大致原理的,比如:
2 可能想不到的点
上面的UML图貌对第三方登陆的原理解释的还可以,但是却有一个比较大的问题,就是用户授权之后是QQ直接把用户的基本信息直接发给CSDN吗?
其实并不是!!!真实的情况是QQ仅仅发给了CSDN一个可以获取当前用户信息的token(令牌),CSDN再拿着这个token去QQ获取当前用户的基本信息。 为什么要用这种模式呢???我们将这个问题拆分成下面两部分来探讨。
2.1 为什么最终还是CSDN去QQ拿用户基本信息,而不是授权后,QQ直接发
其实这个问题是真正理解整个问题的关键。
作为程序猿,我们应该都知道,在实际的项目开发中,80-90%甚至更多的接口是被用来调用的,只有极少数的接口是主动发送请求的。但这并不能作为解释第三方登陆的过程中最终还是CSDN去QQ拿用户基本信息,而不是用户授权后,QQ直接发给CSDN的原因。那原因是什么呢?我觉得
原因是QQ就没必要
且应该也不会
提供主动发送QQ用户基本信息的接口,但是我们大胆地想一想,假如说QQ提供了该接口,该接口的逻辑应该会是这样的:
1.由于QQ用户在QQ授权页面授权了,则QQ可以在内部调用获取用户基本信息的接口拿到该用户的基本信息
2.根据CSDN和QQ建立的某种关系,再将用户基本信息返回给CSDN
那假如又有一个新的需求,需要拿取QQ用户相册里的照片(比如说有个app(或者QQ小程序)想直接拿QQ相册里的相片,它可以将这些相片进行美化。这个需求对于QQ和这个app(或者说QQ小程序)应该是双赢的,对QQ来说,你用户的照片变美了,用户肯定更愿意往QQ相册里存照片,对于这个app(或者说QQ小程序)来说,它可以获取到QQ的广大用户。因此QQ应该会愿意做这件事。),那么QQ也要提供一个用户授权后直接发送QQ相册里照片的接口吗?
这显然是不切实际的,因为这些发送接口对QQ来说简直是鸡肋,QQ明明有可以获取这些数据的接口,为啥还非要写一个相应的发送接口呢? 所以QQ根本不会提供这样的发送接口。
所以只能由CSDN去QQ拿用户的基本信息。
2.2 QQ为啥要给CSDN一个token,这个token有啥用
当差不多明白了为啥只能由CSDN去QQ去拿用户基本信息的时候,自然而然的就会想到另一个问题:既然是你CSDN想访问我QQ的接口获取数据,我QQ必然会对每个请求进行校验,那你CSDN该如何才能被认定为有权限访问我的用户基本信息数据呢???
其实说到这里,又回到了文章开始说的地方,即用户授权之后,CSDN肯定是从QQ那里拿到了什么
的问题上。当然如果CSDN从QQ获取到了QQ号+QQ密码,那带着QQ号+密码去请求QQ获取用户基本信息的接口来拿取相应的用户基本信息,应该是比较爽的,但是上文我们也分析过了,这根本不可能!!!那该咋办呢???
其实到这里,我感觉大家就都应该知道QQ为啥要给CSDN发送一个token了,说白了,就是让CSDN在请求QQ获取用户基本信息的接口时进行校验用的。
那这个token一般会包含哪些信息呢?我猜可能会有下面的信息
①包含请求QQ接口进行认证和授权的信息
②包含具体请求哪个接口的信息->如若不然,一些不怀好意的人拿到该token去获取其他QQ数据咋办
③或许还包含一个有效期
等等吧
3 oauth2协议简介
3.1 oauth2协议到授权码模式
其实上面讨论的问题正是oauth2协议所描述的问题,这里结合上面的uml图用我自己的话来描述一下oauth2协议。
oauth2协议其实是开放授权的一个标准,旨在让用户允许第三方应用(如CSDN)
在未获得账号密码 (某服务器(如微信)的账号密码)的情况下去访问获取该用户在某服务器(如微信)
中的特定私有资源
。
在该协议中涉及到了几个角色,现在介绍如下:
①资源所有者—即我们例子中的用户
②第三方应用—即我们例子中的CSDN,在实际开发中就是指我们自己开发的应用
③服务提供商—用来提供token和特定私有资源,我们例子中的QQ或者说腾讯
④认证服务器—用来认证提供的token等信息是否合法
⑤资源服务器—用来提供用户真正想要获得的数据
其实③、④、⑤只是角色上的划分,完全可以放在一起
该协议在用户进行授权—>第三方应用真正拿到token的这个过程中又分为了四种不同的情况,即所谓的四种授权模式:
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
四种模式中授权码模式是最复杂但却也是最安全的,想利用QQ,微信,微博等进行登陆认证,都需要使用该种模式,因此这里仅对其做一下具体介绍,其他模式可自行百度。
授权码模式的大致流程如下图,即用户授权后,服务提供商并不是直接发令牌给第三方应用而是先发给第三方应用一个授权码;然后第三方应用再拿着这个授权码去服务提供商真正去申请令牌;服务提供商在取到自己发的授权码后,再给第三方应用发放令牌。
3.2 简单理解为什么会有授权码模式
client在整个申请token的过程中向认证服务器进行了两个请求,第一个是拿到授权码,第二次请求是拿着授权码去换取token。也就是说在这个模式下面要求第三方应用必须要有一个服务器,并不是直接返回到浏览器上,安全性会更高。
提示一下:到这里你会不会懵逼?第三方登陆,这所谓的第三方到底指的是谁???
- 在第三方登陆的场景下:QQ,微信等是所谓的第三方
- 但在oauth2协议中所谓的第三方其实指的是我们自己开发的应用(在我们的例子里指的是CSDN)
这里要想通!!!