加载中...
返回

OAuth2.0浅析

本文将介绍开放授权协议的概念,OAuth协议解决的问题以及OAuth协议的设计方案与应用情况。

1. 背景

在生活中,我们接触的各种网络服务通常需要使用我们的个人资源。例如,我们使用网易云音乐,但是选择QQ登录,这时网易云需要获取我们的QQ账号信息,如果双方之间没有一个有效的授权机制,就会对我们的隐私安全造成威胁。试想:网易云音乐如何获取我们的QQ账号信息呢?无非是让我们给出我们的账号密码吧。但是这样做有如下严重的缺点:

  • 我们需要把QQ账号密码告诉网易云音乐,增加了泄露的风险;
  • 网易云音乐拥有了对你的QQ账号的操作权限——想想都头皮发麻;
  • 需要收回网易云音乐对QQ的访问权限时,只能通过修改密码的方式,但是这样做会使其他使用同样方式访问QQ的应用全部失效。

基于此,开放授权(Open Authorization)希望能够使得第三方无需知道用户的账号及密码,就可以获取用户的授权信息。

如果是你,你会怎么实现它?

2. 设计方案

OAuth2.0主要涉及四种角色,分别是:

  • 用户,即资源所有者。
  • 资源服务器,即服务提供商。用来存放受保护的用户资源。在上面的例子中,资源服务器就是QQ服务器。
  • 客户端,向资源服务器进行资源请求的第三方应用程序。在上面的例子中,客户端就是网易云音乐服务器。
  • 认证服务器,在验证资源所有者并取得所有者的授权后,将访问令牌发给客户端。当我们想使用QQ登录网易云音乐,首先就是要证明我们的号主身份,这就是认证服务器的工作——证明身份、取得授权、允许第三方访问。

显然,资源服务和认证服务的提供者都是QQ,因此它们可以运行在同一台服务器上。

OAuth2.0 就是在这四个角色的基础上,设计了四种授权模式:授权码(Authorization Code)模式、简化模式、密码模式和客户端模式。下面就重点一起看一下授权码模式的工作流程。

3. 授权码模式

授权码是认证服务器提供的一串序列,客户端可以凭借授权码向认证服务器索要访问令牌(Access Token),进而实现相应资源的访问。没看懂?举个例子——


还是使用QQ授权登录网易云音乐,我们需要经历如下的流程:

  • 打开网易云音乐,点击“使用QQ登录”;
  • 网易云音乐跟我们说:想使用QQ登录?行,但是我现在没有访问QQ账号的权限,给你张纸条,上面写了我要访问你账号哪些信息,你去找QQ让他同意我访问;
  • 于是我们来到QQ认证界面。QQ首先要我们登录账号,然后跟我们说:网易云音乐想要你的昵称信息、头像信息等等等等,你同意不?
  • 我们选择同意。于是QQ给了我们一张纸条,跟我们说:这个纸条上写了访问你昵称头像信息的授权码,你拿去给网易云音乐,他拿着这个条子来找我,我就让他访问;
  • 于是我们把写着授权码的条子给了网易云音乐,他拿着这个条子去找QQ了,QQ的认证服务器根据这张条子给网易云音乐开出了一个访问令牌(Access Token),网易云拿到了这张令牌,并凭借它成功访问了我们的QQ账号信息。
  • 网易云音乐拿到这个账号信息,在自己数据库里面一查,发现这个QQ账号已经跟某个网易云音乐账号绑定了,于是我们成功使用自己的QQ账号登录了网易云音乐。

这就是非常具象的授权码模式,是不是非常简单?

但是,这里还有一些细节需要思考:

  • QQ会说,我这么没牌面的吗?谁想从我这请求资源我就给他?
  • 在上面的例子中,我们从网易云音乐去找QQ,拿到授权码之后回去找网易云音乐。但是,在真实的浏览器和Web服务器交互的过程中,我们的浏览器可没这么聪明,我们要给它规划好路线才行。

针对第一个问题,OAuth2.0给足了资源服务器面子,它要求:所有的客户端都要在资源服务器那边进行事先的注册,否则直接不给予访问的权限。也就是说,网易云音乐事先已经跟QQ说好了,每次要访问QQ账号信息的时候都会带上身份证明,以表明这是网易云音乐要来访问QQ的资源了。客户端在资源提供方注册的时候,会拿到资源提供方给出的一个client_id和client_secret,之后就用这两个东西表明身份。

而针对第二个问题,我们在向QQ请求授权码的时候,需要提供redirect_uri(或callback_uri)字段,表明浏览器拿到授权码之后要交给谁。于是,授权码模式的完整交互流程如下:

4. 简化模式

看完授权码模式,如果你觉得这个流程有点繁琐,那么简化模式可能会让你快乐一些:

在这个模式中,少掉了授权码的传递,直接传递访问令牌,所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

这样的模式对一些纯前端的网络服务比较友好,因为它不需要资源请求者与资源提供者进行认证交互,直接拿着访问令牌找上门就好了。

但是它叫简化模式,就是因为它存在安全问题。试想:重要的访问令牌就这样在浏览器和资源提供方之间传递,假设攻击者截获了访问令牌,就能够获取到你的资源。

5. 密码模式

在密码模式中,用户向客户端提供自己的用户名和密码。客户端使用这些信息向资源服务器索要授权。这就是我们开头讲过的模式,它要求用户提供自己的用户名和密码,但是客户端不得存储这些信息。显然该模式建立在用户对客户端的高度信任上,通常这里的客户端属于操作系统的一部分,或者由著名的公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才考虑使用这种模式。

6. 客户端模式

客户端以自己的名义,而不是用户的名义,向服务提供商进行认证。严格地说,这种模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求服务提供商提供服务,其实不存在授权问题。

小结

OAuth2.0 协议率先被谷歌、雅虎、微软、FaceBook等公司使用,且目前得到较广泛的普及。之所以标注为2.0,是因为最初有一个1.0协议,但是这个1.0协议太复杂,易用性差,所以没有得到普及。2.0是一个新的设计,但它并不兼容1.0,可以说与1.0没什么关系。

本文简要介绍了OAuth2.0的四种工作方式,通过网易云音乐和QQ的认证交互,希望能使读者对此有初步的认识。关于具体的交互URL,本文没有给出,可以参考文末的一些博客。关于针对OAuth2.0的一些攻击手段,请见下回分解。

参考资料:

[1] 石瑞生,吴旭. 大数据安全与隐私保护[M]. 北京:北京邮电大学出版社,2019

[2] 十八岁的夏天. OAuth2.0的简介. [EB/OL]. [2019-08-19]. https://www.cnblogs.com/xiaofengwang/p/11376881.html

[3] 阮一峰. 理解OAuth2.0. [EB/OL]. [2014-05-12]. http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

10 comments
Anonymous
Markdown is supported
@mpv945
mpv945commentedover 2 years ago

添加图片,如果使用外部图床的http链接 。图片无法点击放大,你那边怎么解决的?

@SGS4ever
SGS4evercommentedover 2 years ago

@mpv945
添加图片,如果使用外部图床的http链接 。图片无法点击放大,你那边怎么解决的?

我的博客没有使用图床,所以没办法帮到你~

@Celetherin
Celetherincommentedover 2 years ago

您好,我也是使用的stack主题,我在照着您的方法添加返回顶部按钮时,遇到了按钮虽然出现、也能够点击,但无法实现实际上的返回顶部功能的问题,我没有任何的代码知识,不知道您有没有解决方法?
另外,也是想提醒一下其他需要这篇教程的朋友,最新版的stack主题,添加返回按钮的组件应该在layouts/partials/sidebar/right.html, 在layouts/_default/single.html中添加代码会导致出现两个右边栏。

@jsjcjsjc
jsjcjsjccommentedover 2 years ago

请教一下博主,如何优雅的给stack主题添加广告哈?
我只想在左或者右侧边栏底部,或者每篇文章底部添加一个小小的广告,但是默认似乎的满屏广告哈~~
感谢

@SGS4ever
SGS4evercommentedover 2 years ago
@ClimbingMouse
ClimbingMousecommentedalmost 2 years ago

你好,按照你的方法设置页面载入动画,这个动画不会停止咋办啊

@46fafa
46fafacommentedalmost 2 years ago

博主你好,请问一下主页布局修改哪里的代码如何作用于整个网页,我发现修改后的布局只存在主页和前两篇文章,其他部分还是没修改的样子

@4kohakunushi
4kohakunushicommentedover 1 year ago

你好,关于左侧栏图标高亮我这里存在一些问题想请教你。我取消了原本主页直接抓取post的内容在中间显示的版块,这个部分改成了其他东西,与此同时新增了一个抓取post信息的与links、search等目录并列的一个目录,现在的问题是这些部分虽然都能正常显示,但是对应的抓取post的那个目录无法选中以后高亮,应该修改增加什么才能让它也可以选中后高亮呢?

@SGS4ever
SGS4evercommentedover 1 year ago

首先我只能基于本文使用的Stack版本来尝试解答,因为没看过当前的Stack主题的代码~
我重新翻了下此前写的关于高亮的内容,理论上只要你的post页面的标题在menu配置中即可高亮。如果post页面是你站点的根路径,那应该可以参考我的文章里写的方法,修改下active的触发逻辑~

@4kohakunushi
你好,关于左侧栏图标高亮我这里存在一些问题想请教你。我取消了原本主页直接抓取post的内容在中间显示的版块,这个部分改成了其他东西,与此同时新增了一个抓取post信息的与links、search等目录并列的一个目录,现在的问题是这些部分虽然都能正常显示,但是对应的抓取post的那个目录无法选中以后高亮,应该修改增加什么才能让它也可以选中后高亮呢?

@sansan-cc
sansan-cccommentedabout 1 month ago

感谢博主的建站帖子,有很大的帮助。

有朋自远方来,不亦说乎?