|
| 1 | +# 01-OAuth 2.0实战-为什么要先获取授权码code |
| 2 | + |
| 3 | +xx软件最终是通过访问令牌请求到我的公众号里的文章。访问令牌是通过授权码换来的。 |
| 4 | + |
| 5 | +为啥用授权码换令牌,直接颁发访问令牌不省事吗? |
| 6 | + |
| 7 | +## 0 OAuth 2.0 组件 |
| 8 | + |
| 9 | +### 0.1 访问今牌(access token) |
| 10 | + |
| 11 | +表示客户端请求的访问权限、对客户端授权的资源拥有者(用户信息)、以及被授予的权限。 |
| 12 | + |
| 13 | +### 0.2 权限范围(Scope) |
| 14 | + |
| 15 | +规定客户端可请求的权限范围。 |
| 16 | + |
| 17 | +### 0.3 刷新今牌(refresh token) |
| 18 | + |
| 19 | +客户端可用刷新令牌向授权服务器请求新的访问令牌,无需用户再次授权,同时刷新令牌还可缩小其权限范围。 |
| 20 | + |
| 21 | +## 1 OAuth 2.0 角色 |
| 22 | + |
| 23 | +### 1.1 资源拥有者 |
| 24 | + |
| 25 | +基本上,资源拥有者就是我们用户自己,我们有权将访问权限授予给客户端。 |
| 26 | + |
| 27 | +### 1.2 客户端(即第三方软件) |
| 28 | + |
| 29 | +xx软件。 |
| 30 | + |
| 31 | +资源拥有者访问受保护资源的软件,即自己的客户端,如我们自己的后台服务、小程序等,他们使用 OAuth2 去获取访问权限。 |
| 32 | + |
| 33 | +### 1.3 授权服务 |
| 34 | + |
| 35 | +公众号开放平台的授权服务。 |
| 36 | + |
| 37 | +如我们系统的 play-auth 服务,授权服务器负责对资源拥有者、客户端进行客户端认证、身份认证,让资源拥有者向客户端授权,为客户颁发访问令牌。 |
| 38 | + |
| 39 | +#### ① 认证服务 V.S 授权服务 |
| 40 | + |
| 41 | +以小程序 web 后台管理系统为例: |
| 42 | + |
| 43 | +- 认证(authentication),你通过啥方式如扫码、用户名密码是否能登录系统 |
| 44 | +- 授权(authorization),认证的下一步,当你认证通过后,返回你拥有的菜单、按钮、数据等功能和数据权限,即系统允许你可进行的操作 |
| 45 | + |
| 46 | +#### ② 认证服务 V.S 网关服务 |
| 47 | + |
| 48 | +独立的认证服务,统一的鉴权服务。 |
| 49 | + |
| 50 | +- 认证服务负责认证,网关负责校验认证和鉴权,其他 API 服务负责处理自身业务逻辑 |
| 51 | +- 安全相关逻辑只存在于认证服务、网关服务,其他服务只是单纯提供服务而无任何安全相关逻辑【减少每个服务的安全校验,抽离公共代码】 |
| 52 | + |
| 53 | +### 1.4 受保护资源 |
| 54 | + |
| 55 | +我的公众号文章。 |
| 56 | + |
| 57 | +受保护的资源是可通过网关访问,但访问时需 oauth2 访问令牌,这些受保护的资源同时要前置验证令牌是否有效、可用,并决定是否要进行响应,通常对受保护资源的鉴权在网关层处理。 |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | +## 2 一定要授权码? |
| 63 | + |
| 64 | +第 4 步授权服务生成授权码,倘若不要授权码而直接返回访问令牌(access_token) 。那就不能重定向,因为这样会把安全保密性要求极高的访问令牌暴露在浏览器,增加访问令牌失窃风险,显然不行! |
| 65 | + |
| 66 | +为规避令牌在前端被劫持风险,若无授权码,就只能把访问令牌发给第三方软件的后端服务: |
| 67 | + |
| 68 | + |
| 69 | + |
| 70 | +看着好像也没问题啊?我访问xx软件,xx软件说要排版文章我得给它授权,不然vx公众号不干,然后xx软件引导我跳转到公众号的授权服务。到授权服务后,开放平台验证xx的合法性及我的登录状态,生成授权页面。我扫码同意授权,于是开放平台知道可将我的文章数据给xx软件了。 |
| 71 | + |
| 72 | +于是,开放平台生成 `access_token`,并通过后端服务方式返回给xx软件,xx就能正常工作。 |
| 73 | + |
| 74 | +但当我被浏览器重定向到授权服务,我和xx间的连接就断了,相当于此时我和授权服务建立连接后,将一直“停留在授权服务页面”。我再也没有重连到xx。 |
| 75 | + |
| 76 | +但这时xx已拿到我授权后的访问令牌,也使用访问令牌获取了我的号里的文章数据。这时,考虑我的感受。xx应该要通知到我,但是如何做呢?现在连接可是断了! |
| 77 | +为了让xx通知到我,我须跟xx重建 “连接”。即第二次重定向,我授权后,又重新重定向回到xx的地址,这样我就跟xx有了新连接。 |
| 78 | + |
| 79 | +为重建连接,又不能暴露访问令牌,就有这**临时、间接凭证:授权码**。因为xx最终要拿到高安全要求的访问令牌,并非授权码,**而授权码可以暴露在浏览器**。 |
| 80 | +有了授权码: |
| 81 | + |
| 82 | +- 访问令牌可以在后端服务间传输 |
| 83 | +- 同时还可重建我 & xx间的连接 |
| 84 | + |
| 85 | +所以,通过授权码,既考虑用户体验,又考虑通信安全。 |
| 86 | + |
| 87 | +执行授权码流程时,授权码和访问令牌在xx和授权服务间到底咋流转的? |
| 88 | + |
| 89 | +## 3 授权码许可类型的通信过程 |
| 90 | + |
| 91 | +### 3.1 间接通信 |
| 92 | + |
| 93 | +间接通信就是指获取授权码的交互: |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | +> 我:“xx,我要访问你了。” |
| 98 | +> xx:“我把你引到授权服务,我需要授权服务给我一个授权码。” |
| 99 | +> 授权服务:“xx,我把**授权码发给浏览器**了。” |
| 100 | +> xx软件:“ 那我从浏览器拿到了授权码。” |
| 101 | +
|
| 102 | +xx和授权服务间,并无直接通信,而是通过中间人(浏览器)。 |
| 103 | + |
| 104 | +### 3.2 直接通信 |
| 105 | + |
| 106 | +授权码换取访问令牌的交互,是“直接”的。 |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | +三方软件xx获取到授权码后,向授权服务发起获取访问令牌 `access_token` 的请求。 |
| 111 | + |
| 112 | +- 三方软件要代表资源拥有者去访问受保护资源 |
| 113 | +- 授权服务负责颁发访问令牌 |
| 114 | +- 受保护资源负责接收并验证访问令牌 |
| 115 | + |
| 116 | +## 4 开发微信小程序场景 |
| 117 | + |
| 118 | +如获取用户登录态信息的过程: |
| 119 | + |
| 120 | +- 通过 `wx.login(Object object)` 获取登录凭证 code,该步是在小程序内部通过调用微信提供的 SDK 而实现 |
| 121 | +- 再通过该 code 换取用户的 session_key 等信息,即官方文档的 `auth.code2Session` 方法,同时该方法也是被强烈建议通过开发者的【后端服务】来调用 |
| 122 | + |
| 123 | +参考 |
| 124 | + |
| 125 | +- https://leokongwq.github.io/2017/02/28/why-oauth2-use-authorization-code.html |
| 126 | +- https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html |
| 127 | +- https://segmentfault.com/q/1010000014642301 |
| 128 | +- https://tools.ietf.org/html/rfc6749 |
0 commit comments