我正在参加「掘金·启航计划」
1、应用场景
1.1、快递员问题:
我住在一个大型的居民小区。小区有门禁系统.进入的时候需要输入密码。我经常网购和外卖,每天都有快递员来进出。我必须找到一个办法,让快递员通过门禁系统,进入小区。
如果我把自己的密码,告诉快递员,他就拥有了与我同样的权限,如果他把密码告诉了别人,别人随便出入,那更不安全。万一我想取消他进入小区的权力,也很麻烦,我自己的密码也得跟着改了,还得通知其他的快递员。
有没有一种办法,让快递员能够自由进入小区,又不必知道小区居民的密码,而且他的唯一权限就是送货,其他需要密码的场合,他都没有权限?
1.2、门禁授权
为了解决这个问题,可以设计一个门禁授权系统:
第一步,门禁系统的密码输入器下面,增加一个按钮,叫做"获取授权"。快递员需要首先按这个按钮,去申请授权。
第二步,他按下按钮以后,屋主(也就是我)的手机就会跳出对话框:有人正在要求授权。系统还会显示该快递员的姓名、工号和所属的快递公司。
我确认请求属实,就点击按钮,告诉门禁系统,我同意给予他进入小区的授权。
第三步,门禁系统得到我的确认以后,向快递员显示一个进入小区的令牌(access token)。令牌就是类似密码的一串数字,只在短期内(比如七天)有效。
第四步,快递员向门禁系统输入令牌,进入小区。
有人可能会问,为什么不是远程为快递员开门,而要为他单独生成一个令牌?这是因为快递员可能每天都会来送货,第二天他还可以复用这个令牌。另外,有的小区有多重门禁,快递员可以使用同一个令牌通过它们。
1.3、互联网场景
将门禁授权机制的设计思路类比到互联网场景中,
首先,居民小区就是储存用户数据的网络服务。比如,微信储存了我的好友信息,获取这些信息,就必须经过微信的"门禁系统"。
其次,快递员(或者说快递公司)就是第三方应用,想要穿过门禁系统,进入小区给我送取快速。
最后,我就是用户本人,同意授权第三方应用进入小区,获取我的数据。
2、设计思路
为了让”快递员“安全可控的进入“小区”,而且避免密码的泄露问题,所以设计了“门禁授权系统”,这个门禁授权的流程,对比与互联网场景的“第三方应用”和“资源服务器”,就是设置一个授权层。

OAuth 2.0的设计思路就是这个样子,OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。
- "客户端"不能直接登录"资源服务器",只能登录授权层,以此将用户与客户端区分开来。
- "客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。
- "客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。
OAuth的作用:让"客户端"安全可控地获取"用户"的授权,与"资源服务器"进行交互。
2.1、令牌和密码
对比令牌和密码:
| 令牌(token) | 密码(password) | |
|---|---|---|
| 时效 | 短期的,到期会自动失效,用户自己无法修改 | 长期有效,用户不修改,就不会发生变化 |
| 允许撤销 | 可以被数据所有者撤销,会立即失效 | 密码一般不允许被他人撤销 |
| 权限范围 | 权限范围(scope),比如只能进小区的二号门 | 密码一般是完整权限。 |
注意:只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因。
2.2、基本概念
| 名称 | 含义 |
|---|---|
| Third-party application | 第三方应用程序,又称“客户端”(client),即例子中的“快递员” |
| Resource Owner | 资源所有者,又称“我”(user)。 |
| User Agent | 用户代理,本文中是指浏览器。 |
| Authorization server | 认证服务器,即服务提供商专门用来处理认证的服务器 |
| Resource server | 资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。 |
3、运行流程
- (A)用户打开客户端以后,客户端要求用户给予授权。
- (B)用户同意给予客户端授权。
- (C)客户端使用上一步获得的授权,向认证服务器申请令牌。
- (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
- (E)客户端使用令牌,向资源服务器申请获取资源。
- (F)资源服务器确认令牌无误,同意向客户端开放资源。