今天我们来讲解一下OAuth2,在平时应用中我们经常能够见到它的身影。比如,当微信小程序获取你的用户名和头像时需要你授予权限,以及当我们在网站上使用微信或QQ登录时也是使用到了OAuth2。接下来我们便来讲解一下OAuth2。

一、什么是OAuth2

OAuth 2.0是目前最流行的授权机制,用来授权第三方应用,获取用户数据。

OAuth(开放授权)是一个关于授权的开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息(比如照片、视频、用户信息等),而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0。即完全废止了OAuth1.0。OAuth 2.0协议正式发布为RFC-6749。

OAuth2主要包含以下特点:

  • 用于REST/APIs的代理授权 框架(delegated authorization framework)

  • 基于令牌Token的授权, 在无需暴露用户密码的情 况下,使应用能获取对用 户数据的有限访问权限

  • 解耦认证和授权

  • 事实上的标准安全框架,支持多种用例场景

    • 服务器端WebApp
    • 浏览器单页SPA
    • 无线/原生App
    • 服务器对服务器之间

二、OAuth2的原理

在常规情况下应用请求资源服务器, 访问客户数据,在没有OAuth2的情况下,资源服务器区分不出请求过来的应用是恶意用户还是其他用户,数据都会返回。 如下图所示:


因此为了用户安全访问数据,在访问中间添加了Access Token机制。客户端需要携带Access Token去访问受到保护的资源。


OAuth2就是让我们使用授权服务器颁发给客户应用Access Token。

最后客户端拿到Access Token去资源服务器进行校验,验证通过之后才返回数据。

OAuth2的整体流程图如下:

  • (A)客户端向资源所有者请求授权。授权请求可以直接对资源所有者(如图所示)进行,或者通过授权服务器作为中介进行间接访问(首选方案)。
  • (B)资源所有者允许授权,并返回凭证(如code)。
  • (C)客户端通过授权服务器进行身份验证,并提供授权凭证(如code),请求访问令牌(access token)。
  • (D)授权服务器对客户端进行身份验证,并验证授权凭证,如果有效,则发出访问令牌。
  • (E)客户端向资源服务器请求受保护的资源,并通过提供访问令牌来进行身份验证。
  • (F)资源服务器验证访问令牌,如果正确则返回受保护资源。

简单说就是:客户应用向授权服务器请求Access Token —> 授权服务器向用户征询意见,是否将权限授予客户应用 —> 用户同意 —> 授权服务器生成颁发Access Token给客户应用 —> 客户应用拿着Access Token去请求资源服务器 —> 资源服务器验证客户应用的Access Token —> 验证通过,返回数据

三、OAuth2中的角色和术语

在OAuth2中主要有四个角色,主要如下:

  1. Resource Owner(资源所有者):用户,即资源的拥有人,想要分享某些资 源给第三方应用
  2. Resource Server(资源服务器):放受保护资源,要访问这些资源,需要获得访问令牌
  3. Authorization server(授权(认证)服务器):授权服务器用于发放访问令牌给客户端
  4. Client(客户端(第三方应用)):客户端代表请求资源服务器资源的第三方程序

OAuth2中的其他术语:

  • Client Credentials(客户凭证):客户的clientId 和密码用于认证客户
  • Access Token(访问令牌):授权服务器在接收到客户请求后,颁发的访问令牌
  • Scopes(作用域):客户请求访问令牌时,由资源拥有者额外指定的细分权限(permission)
  • User Agent(用户代理):用户代理。一般就是指浏览器

OAuth2中的令牌类型:

  • Authorization Code Token(授权码):仅用于授权码授权类型,用于交换获取访问令牌和刷新令牌
  • Refresh Token(刷新令牌):用于去授权服务器获取一个新的访问令牌
  • Access Token(访问令牌):用于代表一个用户或服务直接去访问受保护的资源
  • Proof of Possession(PoP) Token(持有证明(pop)令牌):可以校验client是否对Token 有明确的拥有权

通过上面的介绍我们大概总结如下:

  • OAuth的本质在于如何获取token,如何使用token
  • OAuth是一种在系统之间的代理授权(delegation authorization)协议
  • OAuth提供一个宽泛的协议框架,具体安全场景需要定制
  • OAuth使用代理协议的方式解决密码共享反模式问题

四、OAuth2的四种授权方式

从运行流程不难看出,要获取access token必须先得到用户授权(authorzation grant),那么如果获取这么用户授权呢?OAuth 2.0定义了四种类型的授权类型

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)
1、授权码模式(authorization code)

授权码模式是功能最完整、使用最广泛、流程最严密的授权模式。

授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。

第一步:用户访问客户端,客户端将用户导向授权服务器,通过用户代理(User-Agent)发送包括它的客户端标识符、请求的范围、本地状态和一个重定向URI,授权服务器在授予(或拒绝)访问权后将其发送给用户代理。URI如下:

http://localhost:8080/oauth/authorize?client_id=clientapp&redirect_uri=http://localhost:9001/callback&response_type=code&scope=read_userinfo

在URI中response_type参数表示要求返回授权码(code),client_id参数让授权服务器知道是谁在请求,redirect_uri参数是授权服务器接受或拒绝请求后的跳转网址,scope参数表示要求的授权范围(这里是只读)。

第二步:授权服务器对资源所有者进行身份验证(通过用户代理,让用户输入用户名和密码),并确定资源所有者是否授予或拒绝客户端的访问请求。

第三步:用户跳转后,假如资源所有者同意授权请求,那么授权服务器将会使用前面提供的或者事先指定的重定向URI(redirection URI),重定向到客户端,并附上一个授权码(code)和一个前面提供的本地状态(state)(如果有的话,则会原值返回)。

http://localhost:9001/callback?code=ghN0hf

第四步:客户端收到授权码,附上早先的重定向URI,向授权服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。在发出请求时,授权服务器对客户端进行身份验证。请求参数包含授权代码、用于获得验证的授权代码的重定向URI、标识客户端身份的client id和client secret。

 http://localhost:8080/oauth/token?client_id=clientapp&client_secret=123&code=ghN0hF&grant_type=authorization_code&redirect_uri=http://localhost:9001/callback&scope=read_userinfo

注意:用户密匙和密码可以在headers里添加认证,Authorization。

上面 URL 中,client_id参数和client_secret参数用来让授权服务器确认客户端的身份(client_secret参数是保密的,因此只能在后端发请求),grant_type参数的值是authorization_code,表示采用的授权方式是授权码,code参数是上一步拿到的授权码,redirect_uri参数是令牌颁发后的回调网址。

第五步:授权服务器对客户端进行身份验证,验证授权代码,并确保所收到的重定向URI与用于在步骤©中对客户端重定向的URI相匹配,如果有效,授权服务器将发送访问令牌access token和刷新令牌refresh token(可选)。

然后授权服务器给我们返回授权码,如下:

{"access_token": "36cded80-b6f5-43b7-bdfc-594788a24530","token_type": "bearer","expires_in": 43199,"refresh_token":"45cdce99-b6f5-8866-bdfc-764745a45780","scope": "read_userinfo"
}

这里的参数主要是:

  • access_token:表示访问令牌。必选项。
  • token_type:表示令牌类型。该值大小写不敏感,必选项,可以是bearer类型或mac类型。
  • expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • refresh_token:表示更新令牌。可选项,用来获取下一次的访问令牌。
  • scope:表示权限范围。可选项,如果与客户端申请的范围一致,此项可省略。

最后我们拿到access_token去访问受保护的资源即可,如下:

http://localhost:8080/api/userinfo?access_token=f4345f3a-34a3-4887-bc02-e95150c54bf4
2、简化模式(implicit)

简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

第一步:用户访问客户端,客户端将用户导向授权服务器,通过用户代理(User-Agent)发送包括它的客户端标识符、请求的范围、本地状态和一个重定向URI,授权服务器在授予(或拒绝)访问权后将其发送给用户代理。URI如下:

http://localhost:8080/oauth/authorize?client_id=clientapp&redirect_uri=http://localhost:9001/callback&response_type=token&scope=admin&state=abc

这一步为直接申请授权token,参数和申请授权码类似,client_id,redirect_uri回调地址,response_type有变动,改为直接获取token,scope权限,state用于认证标记,传过去什么回调时传回来什么。

第二步:授权服务器对资源所有者进行身份验证(通过用户代理,让用户输入用户名和密码),并确定资源所有者是否授予或拒绝客户端的访问请求。

第三步:用户跳转后,假如资源所有者同意授权请求,那么授权服务器将会使用前面提供的或者事先指定的重定向URI(redirection URI),重定向到客户端,并附上访问令牌等信息。如下:

http://localhost:9001/callback#access_token=0406040a-779e-4b5e-adf1-bf2f02031e83&token_type=bearer&state=abc&expires_in=119

同理,我们拿到access_token就可以访问受保护的资源了。

http://localhost:8080/api/userinfo?access_token=0406040a-779e-4b5e-adf1-bf2f02031e83
3、密码模式(resource owner password credentials)

密码模式中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。

在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

第一步:用户访问客户端,客户端将用户导向授权服务器,然后提供URI连接包含用户名和密码信息给授权服务器。如下:

 http://localhost:8080/oauth/token?client_id=clientapp&client_secret=123&username=anumbrella&password=123456&grant_type=password&scope=admin

注意:用户密匙和密码(client_id和client_secret)可以在headers里添加认证,Authorization。

第二步:授权服务器认证用户名和密码信息正确后,然后返回客户端access_token等信息,如下:

{"access_token": "58a02fd5-87f5-44ff-bbdd-d429cf6a2f60","refresh_token":"45cdce99-b6f5-8866-bdfc-dtfsdft55780","token_type": "bearer","expires_in": 43199,"scope": "admin"
}

同理,拿到access_token即可访问我们需要访问的资源。

4、客户端模式(client credentials)

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

第一步:客户端直接向授权服务器发起认证请求,URI如下:

 http://localhost:8080/oauth/token?client_id=clientapp&client_secret=123&grant_type=client_credentials&scope=admin

注意:用户密匙和密码(client_id和client_secret)也可以在headers里添加认证,Authorization。

第二步:授权服务器通过认证后,直接返回客户端access_token等信息,如下:

{"access_token": "776b162a-949e-4dcb-b16b-9985e8171dc0","refresh_token":"46ffdtfa-b6f5-8866-bdfc-dtfsdft55780","token_type": "bearer","expires_in": 43188,"scope": "devops"
}

最后我们拿到access_token即可访问相关资源。

好了,OAuth2相关基本概念就到这里了,后面再介绍相关实战知识,请持续关注。最近换工作了,所以时间比较紧,博客更新有点点慢,后面我会多抽时候把计划的相关体系的知识点都保量保质更新起走,欢迎大家关注!!

参考

  • OAuth2基本概念和运作流程
  • https://tools.ietf.org/html/rfc6749
  • https://oauth.net/2/
  • OAuth 2.0 的四种方式

OAuth2学习(一)——初识OAuth2相关推荐

  1. spring oauth2学习笔记

    一 主要参考资料 https://echocow.cn/articles/2019/07/14/1563082088646.html 1.1 博客地址: echocow.cn[重点关注,对应的代码路径 ...

  2. OAuth2学习(二)——OAuth2实战

    在上一篇文章中我们讲解了OAuth2的一些基本概念,对OAuth2有了基本的认识.这一节内容我们就讲解一下OAuth2实战,围绕OAuth2的基本类型进行实战讲解. 授权码模式(authorizati ...

  3. Spring Security OAuth2学习

    文章目录 Spring Security 简介 依赖 配置类 自定义UserDetailsService 分布式认证需求 认证方案 OAuth2 jwt Spring Security Oauth2. ...

  4. Nancy in .Net Core学习笔记 - 初识Nancy

    原文:Nancy in .Net Core学习笔记 - 初识Nancy 前言 去年11月份参加了青岛MVP线下活动,会上老MVP衣明志介绍了Nancy, 一直没有系统的学习一下,最近正好有空,就结合. ...

  5. Nacos学习之初识Nacos

    Nacos学习之初识Nacos 在分布式项目中既然存在Eureka这个注册中心,那么Nacos有充当什么角色?Nacos到底是个啥?他又是咋么下载安装的?本文我会将从什么是Nacos.Nacos与其他 ...

  6. PE病毒学习笔记——初识感染技术 (转自看雪学院)

    [分享]PE病毒学习笔记--初识感染技术 <script type="text/javascript"></script>   标 题: [分享]PE病毒学 ...

  7. 前端学习(初识HTML 上)——基础知识和基本标签

    前端学习之初识HTML 一.HTML基础知识 1.html定义 2.html特点 3.html标签 4.html基础结构 (1)<head></head>中的<meta& ...

  8. Oauth2学习笔记

    直接上代码了,都是齐雷老师教的,本文为梳理笔记 理解Oauth2.0: http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 创建父工程 1. 创 ...

  9. SpringSecurity OAuth2学习心得

    心得 第一次整合项目大致如下! 这种是我刚上手刚学会爬的时候写的,写的比较粗糙,而且有一几个很致命的问题:一是没有将资源服和授权服务独立分开,导致了一些问题产生,当然这个问题我也以文章的形式记录下来, ...

最新文章

  1. NR 5G RRC无线资源控制
  2. cordova contacts测试
  3. AOE网(求关键路径)(c/c++)
  4. 切面是异步还是同步操作‘_Autofac的AOP面向切面编程研究
  5. 关于SparkStreaming的checkpoint的弊端
  6. 内核启动的C语言阶段——start_kernel函数
  7. PAT乙级(1029 旧键盘)
  8. java将图片写入pdf
  9. 5个小技巧让你写出更好的JavaScript 条件语句
  10. 电影院购票系统ssm (含论文)
  11. 拼多多商家后台开放平台API
  12. 邮箱容量多大?163邮箱发邮件无限容量解读
  13. 笔试——字符串算法题——寻找最大回文子串
  14. C# 开发的 webBrowser打开网页出现脚本错误解决
  15. 花花公子推荐伤感qq日志:乖不哭,我拜你
  16. c语言指针化简带分数,自动生成四则运算题目(C语言)
  17. EIGRP(Enhanced Interior Gateway Routing Protocol,增加型内部网关路由协议)
  18. 数据清洗的一般方法和步骤
  19. 东方式插花注重花材所表达的内容美
  20. 一键重装系统win7教程

热门文章

  1. python单位根检验平稳性怎么看是否平稳_Python ADF 单位根检验 如何查看结果的实现...
  2. 网络舆情如何有效预警的方式方法详解
  3. 2013c语言二级等级考试试题,计算机等级考试二级c语言考试试题
  4. 自然语言处理(七):AG_NEWS新闻分类任务(TORCHTEXT)
  5. 微型计算机原理实验二,微机原理实验2
  6. 绿联扩展坞拆解_用过才知道,华为P30搭配绿联扩展坞可实现众多有趣玩法
  7. 营销-营销方式:营销方式
  8. /etc/sysconfig/network: 没有那个文件或目录
  9. 一个成功软件测试项目的经验(转载)
  10. 如何使用 minio 进行 BR 备份