OAuth2原理又忘了?

工作中碰到有些同学理解不了OAuth2,而我自己在项目中使用过也是比较早以前的事情了,所以如果突然要说出具体原理或者举个具体的例子来,虽然自己口口声声已经彻底理解了却还是说不太清楚。因此,这篇文章我将化繁为简,举两个使用这个协议的例子,让大家通过这个简单的方法理解其中的原理。

说到OAuth2一般就会提到单点登录,而实际上不管是否有单点登录系统,都可以使用OAuth2。这里面主要有四个角色,分别是资源拥有者、认证服务器、资源服务器、客户端应用,其中关系如下图所示:

简单来说,就是客户端应用要访问资源服务器时,需要先经过资源拥有者的同意,然后客户端应用向认证服务器请求访问资源服务器所需要的token,接着再拿个token去访问资源服务器的资源。这里隐含的条件是,认证服务器和资源服务器之间有一个契约,也就是对token的授权和解析方式。具体的请求流程,可以看看下面这张图:

一般来说,客户端应用先向资源拥有者申请访问权限,这时候客户端应用会将用户重定向到认证服务器的登录界面,用户登录成功后得到一个Authorization code,即授权码,然后拿这个授权码去向认证服务器请求Access token,即访问令牌,拿到Access token后,客户端应用再拿它去访问资源服务器被保护起来的资源,整个流程就完成了。在实际中,有时候认证服务器和资源服务器也会是同一个,客户端应用往往是客户端UI对应的服务器端应用,也就是说,拿授权码去获取Access token的行为,是发生在客户端应用的服务器端和认证服务之间。

下面来看两个可能(没有深究过)使用了这种方式的例子。

例子1:使用微信登录新浪微博

用户在微博登录界面点击微信图标,这时候跳转到一个二维码界面,用户拿起手机,用微信APP扫描二维码,这时用户APP会出现界面提示用户是否允许使用微信登录微博,用户选择“同意”,微博登录成功。其中的流程大致如下:

1.用户点击微信登录时,微博转到二维码界面,这个二维码包含了微信认证服务器的地址、微博的回调地址等信息;

2.用户微信扫码时,解析出是微博需要使用该微信登录,这里可能涉及微信和微博之间的某种加解密协议;

3.用户选择“同意”,这时候微信认证服务器调用微博的回调地址,并把授权码返回给它;

4.微博使用这个授权码,向微信认证服务器请求Access token;

5.微博获取到Access token后,拿去访问微信的资源服务器,获取微信用户的某些信息;

6.微博拿获取到的微信用户信息,然后去查找微博的数据库用户表,看是哪个用户绑定了该微信,再拿这个用户信息去登录微博服务器;

例子2:用户群重叠网站之间的自动登录

由于某些原因,两个网站A、B共享用户,但可能记录的用户信息又不完全一样,或者共享用户数据库但又各自有自己的登录模块。当用户已经登录了网站A时,这时候从A网站跳转到B时,我们希望在访问B网站时也处于登录状态。这个时候,可以使用大致如下流程:

1.用户访问网站A,并且已经登录;

2.用户点击B网站的链接,这时候重定向到A网站的登录模块,并带上B网站的回调链接;

3.A网站服务端调用B网站的回调链接,并给其返回授权码;

4.B网站拿授权码继续向A网站申请Access token;

5.B网站拿Access token去访问A,获取当前客户端登录用户的信息;

6.B拿获取到的用户信息去登录自己的服务器端,然后可以调用A的回调函数,在里面重定向到B网站的某个界面;

例子就讲到这里了。很多人会对授权码Authorization code产生困惑,不明白为什么需要先拿到授权码再去获取Access token,而不能一次到位。其实这是出于安全性的考虑。前面我们说,在重定向到认证服务器的时候,是带一个回调地址的,认证服务器就是通过这个地址将授权码返回给客户端应用的。而对于第三方的客户端应用,这个回调地址可能都不用https,如果直接返回Access token并且被窃取了,那就相当于密码被泄露一样。而如果只是返回授权码,然后客户端应用再拿授权码去认证服务器获取Access token时,认证服务器可以保证自己的访问链接是https的,所以认证服务器在返回Access token是有安全保证的。对于授权码来说,即使被中间人窃取了,但因为中间人不知道client_id和client_secret,这些信息是保存在客户端应用的服务器上的,因此中间人无法通过组合client_id、client_secret、authorization code这三者以便从认证服务器拿到Access token。除非比较极端的情况下,比如中间人也控制了客户端应用服务器,那就难办了,但作为一个协议来说,它也只能针对普遍的问题提供通用的解决方案,对极端情况来说,它是无能为力的,需要我们通过其它方式去解决。

欢迎长按扫码关注【技术人成长】视频号,与你分享更多技术人成长的心法,我们视频上见!