这是我参与更文挑战的第22天,活动详情查看: 更文挑战前端
OAuth 2.0 是一种 安全协议,今天聊一聊微信小程序的常规登陆受权流程和背后的原理。ios
登陆认证是一个完整应用必备的模块,小程序和微信是一种相似应用与平台的关系,小程序属于微信公众平台,同一个平台下还有微信公众号:web
在技术角度上,小程序与微信的关系比公众号更密切,由于公众号的文章本质上是一个 H5 网页,对微信底层的依赖比小程序弱;编程
从产品角度上,两者与微信的关系一致,都是运行在微信平台上的第三方应用。小程序
根据微信官方文档描述,开发者获取用户登陆态信息的过程正是一个受权码的许可流程:首先,开发者经过 wx.login(Object object) 方法获取到登陆凭证 code 值,这一步的流程是在小程序内部经过调用微信提供的 SDK 实现;而后,再经过该 code 值换取用户的 session_key 等信息,也就是官方文档的auth.code2Session 方法,同时该方法也是被强烈建议经过开发者的后端服务来调用的。后端
这个过程并无使用到浏览器,但确实按照受权码许可的思想走了一个完整的受权码许可流程。也就是说,先经过小程序前端获取到 code 值,再经过小程序的后端服务使用 code 值换取 session_key 等信息,只不过是访问令牌 access_token 的值被换成了 session_key。微信小程序
既然小程序是微信平台的第三方应用,那么在接入微信登陆时就要严格遵照官方的接入规范。而在互联网技术领域,对于支持第三方应用接入的平台,在登陆受权上有一套标准的技术规范:OAuth 2.0。浏览器
开始以前,你仍是要先回想下生活场景,用户小明登陆某电商小程序,而且想要访问本身双十一的订单,这时候第三方软件玄武受权订单数据的整个流程。咱们说第三方软件先要让小明去微信商家开放平台那里给它受权数据,那这里是否是你以为很奇怪?安全
你总不能说,“嘿,微信平台,你把数据给第三方软件玄武(你想象成某快递软件也能够)用吧”,那微信平台确定会回复说,“小明,玄武是谁啊,没在咱家备过案,我不能给他,万一是骗子呢?”对吧,你想一想是否是这个逻辑。因此,受权这个大动做的前提,确定是玄武要去微信平台那里“备案”,也就是注册。注册完后,微信商家开放平台就会给玄武软件 app_id 和app_secret 等信息,以方便后面受权时的各类身份校验。同时,注册的时候,第三方软件也会请求受保护资源的可访问范围。好比,玄武可否获取小明店铺 3 个月之前的订单,可否获取每条订单的全部字段信息等等。这个权限范围,就是 scope。 备完案以后,我们接着继续前进。小明过来让平台把他的订单数据给第三方软件玄武,平台咔咔一查,对了下暗号,发现第三方软件玄武是合法的,因而就要推动下一步了。 在受权码许可类型中,受权服务的工做,能够划分为两大部分,一个是颁发受权码 code,一个是颁发访问令牌 access_token。服务器
经过简单的受权码场景能够了解到,微信为宿主的小程序使用微信登陆是一件理所固然的事儿,但其实小程序并无强制要求只能使用微信登陆,也能够跟 Web 网站同样使用帐户密码模式、邮箱、手机号等登陆方式。既然如此,为何咱们必定要使用微信登陆呢?由于除了便利性之外,微信登陆更重要的优点是整合了微信庞大的生态系统,以及对于产品策略的加持。
小程序是微信平台上的一款第三方应用,在登陆方式的选择上有很高的自由度,微信登陆仅仅是其中一个选择,你彻底可使用跟其余应用(网站、App)同样的登陆方式,好比手机号、邮箱、用户名密码等。 事实上微信小程序仅仅是众多Web产品矩阵中的一个应用端,同时存在的还有网站、App 等应用端。从生态系统的角度上,相对于其余应用端,以微信为入口的小程序最大的优点是拥有微信完善的生态系统,用户使用微信登陆后可使用微信提供给小程序的各类平台级能力,好比订阅消息、微信支付、小程序直播、音视频对话等。
从用户体验的角度上,使用微信登陆,用户可以很大程度上下降登陆的复杂程度,无形中提升用户的登陆成本和用户体验。从产品策略的角度上,使用微信登陆小程序可以根据用户的来源,制定特殊的产品策略,好比对于小程序的用户发放商家优惠券、订阅消息等等。
因此由此得出小程序使用微信登陆的三个主要优点:
这说明了小程序接入微信登陆的必要性,那它的登陆流程是什么呢?以下图:
整个登陆流程中描述了三种角色和六个术语,了解它们的定位和做用,是理解小程序登陆流程的基础。
登陆流程里的三个角色,客户端在整个登陆流程中主要承担两种行为:
不过客户端的全部信息和网络请求几乎都是能够被破解或拦截的,因此出于安全的考虑,小程序登陆流程中的一些接口被限制不能在客户端中直接调用,而是须要在服务端发起,开发者服务的工做即是处理这些安全敏感的网络请求,体现为上图中使用code 获取 openid 和 session_key的请求,这个请求使用了微信提供的 auth.code2Session 接口。
而微信接口服务的工做对于开发者来讲是不透明的,你须要作的仅仅是根据接口的规范,组装网络请求发送给它,而后根据返回的接口执行分发逻辑。微信服务器会验证网络请求的合法性,对于合法请求下发密钥 session_key 和用户 openid。
它是在小程序内经过 API wx.login 获取的,而后经过 HTTP 请求发送给开发者服务器。code 的做用体如今“临时”两字上,它的有效期限仅有 5 分钟,而且仅可以使用一次(即请求一次 auth.code2Session 接口)。
每一个微信小程序在注册时就会生成一个惟一的appid,这个 ID 标记了小程序的惟一性,等同于网站的URL(通过备案的)、App 的包名等标记应用惟一性的信息。
它是小程序的密钥,能够在微信公众平台的后台管理系统中获取。appsecret 是很是私密的信息,因此微信在制定小程序登陆的流程时,将携带此信息的网络请求限制在只能经过开发者服务器发送给微信接口服务,这样对于客户端来讲是不可见的,进而下降了被泄露的可能性。与appid 不一样的是,appsecret 能够被重置,但每次重置以后,历史的 appsecret 便会失效。
微信对于用户 openid 的定义是:微信号在某个应用程序中的惟一 ID。这里的“某个应用程序”(好比兰蔻小程序)指的是小程序、公众号、接入开放平台的应用。微信生态中目前有公众平台和开放平台两种,其中公众平台又细分为小程序和公众号,开放平台能够接入网站、移动应用等。同一个微信号在不一样的应用程序中有不一样的 openid。
在微信生态下另外有一个标记微信号的惟一 ID:UnionId。这个 ID 跟应用程序无关。因此,能够简单地理解为 openid 是 UnionId 与 appid 综合加密后的结果。
UnionId 一般用来关联在不一样应用程序中各个 openid ,好比同一个微信号在小程序和公众号内须要配置一样的权限,仅经过 openid 没法实现,便须要获取此微信号的 UnionId。
session_key 是对用户数据进行加密签名的密钥,微信服务器使用它将用户的数据进行加密和解密。你能够简单地将 session_key 理解为获取用户数据的“绿卡”,登陆以后全部涉及访问微信服务器的请求通常都须要带上它,微信服务器会校验 session_key 的合法性。
其实到这一步(即拿到了 openid 和 session_key)已经完成了小程序的登陆流程,但对于一个应用程序来讲,用户进行登陆操做应该是“一劳永逸”的,即登陆过一次以后在必定时间以内的后续操做都不须要再次登陆,用技术语言描述就是应该保存用户的登陆态。这个时候就须要用到接下来的一个术语:token。
登陆态是个逻辑词汇,token 能够理解为登陆态的具象化、数据化。在小程序的登陆流程图中,你能够看出,token是由开发者服务器建立的一个字符串,并且须要跟 openid 和 session_key 相关联。其实这里并非强制关联 openid,由于 openid 并不算是私密信息,能够放心地下发到客户端(即小程序)。可是 session_key 是很是私密的信息,一旦泄露有很大的安全隐患,因此强烈建议不要把它下发到客户端。
在获取到 openid 和 session_key 以后,开发者服务器建立一个 token,而后与 openid 和session_key 进行关联,具体的方法根据服务器编程语言的不一样有多种实现方案。我们以JavaScript 语言做为示例,能够建立一个对象,对象的 key 是 token 的值,value 是一个包含 openid 和 session_key 的对象,以下:
{
"token_1": {
"openid": "获取到的openid 1",
"session_key": "获取到的session_key 1"
},
"token_2": {
"openid": "获取到的openid 2",
"session_key": "获取到的session_key 2"
},
}
复制代码
关联完成以后开发者服务器将 token下发到客户端,客户端保存在本地,后续的全部请求均须要携带此 token,携带的方法并无既定的规范,能够经过 URL Query、HTTP Body、Header 等,但一般建议经过 Header 传递,这样相对来讲更安全一些。
OAuth 2.0 这种受权协议,就是保证第三方(软件)只有在得到受权以后,才能够进一步访问受权者的数据。这里的受权服务和受保护资源服务都是微信商家开放平台(不过应该是对应受权服务和订单服务)、客户端(第三方软件)对应的是玄武软件、资源的拥有者小明经过OAuth2.0的受权码模式受权后,第三方软件玄武能够访问对应的订单,
我们先思考一个问题:小程序登陆以后若是须要访问用户的数据(好比昵称、地域、性别等)须要获得谁的受权?是微信?仍是用户? 答案是用户。用户的数据虽然存放在微信的服务器之上,可是这些数据的全部权属于用户本身,而不是微信。这里其实引出了 OAuth 2.0 规范中的两个基本概念。
而小程序在获取用户数据中的角色是做为微信平台的第三方应用程序,在 OAuth 2.0 规范中的术语为 Third-party application。 除了以上三种角色以外,OAuth 2.0规范中还有另外三种角色:
小程序依托于微信提供的底层技术平台,微信为小程序提供了与用户(即Resource Owner)沟通的工具,它在 OAuth 2.0 规范中的角色被称为 User Agent(用户代理)。 微信服务器不只仅做为 Resource Server 保存用户数据,同时在登陆受权过程当中又提供了HTTP服务以及受权认证功能,这两个功能的角色在 OAuth 2.0 规范中分别被称为 HTTP Service(HTTP服务提供商)和Authorization server(认证服务器)。
以上即是 OAuth 2.0 规范中的全部角色,为了增强了解,咱们再梳理一遍:
Resource Owner
(资源全部者):在小程序场景下表明小程序的用户。
Resource Server
(资源服务器,即存放用户数据、资源的服务器):在小程序场景下这个角色由微信服务器承担。
Third-party application
(第三方应用程序/又称客户端):在小程序场景下表明小程序。
User Agent
(用户代理):在小程序场景下表明微信。
Authorization server
(认证服务器):在小程序场景下,这个角色由微信服务器承担。
HTTP Service
(HTTP 服务提供商):在小程序场景下,这个角色由微信服务器承担。
看到这里,可能以为 OAuth 2.0 规范中的角色与小程序登陆流程中角色不同?
其实,小程序登陆流程中的三个角色是按照实体划分的,而 OAuth 2.0 规范的角色是按照功能划分的,同一个实体能够担任一种或多种功能。 在小程序登陆流程中的 3 个实体角色中,微信同时担任 Third-party application 和User Agent 的功能;微信服务器同时担任 Resource Server、Authorization server 和HTTP Service 的功能;开发者服务器比较特殊,它即担任 HTTP Service 的功能,同时在认证流程中因为须要转发和关联 token,因此也充当了客户端的一部分功能。
好比你向邻居借了衣架忘了还,某天邻居着急使用所才打电话向你要回,不巧的是你正在外地出差家里没人。但好在你家的门锁是智能门锁,你能够将密码告诉邻居让他本身去你家里取。可是你本着“防人之心不可无”的心理,担忧邻居是否会趁机记下甚至修改你家的门锁密码。左右为难的时候,你忽然想起来你家的智能门锁能够建立临时密码,这种临时密码只能在 10 分钟以内有效,并且没有修改本来密码的权限。因此,最终你在手机上建立了一个临时智能门锁的密码发给你的邻居。
OAuth 2.0 规范要解决的问题与上面提到的这个现实案例很是类似,简单归纳就是:OAuth 2.0是一个受权机制,资源全部者告诉认证服务器,临时授予某个第三方应用访问资源服务器获取资源的权限,认证服务器给第三方应用颁发一个临时令牌,拥有这个令牌即可以获取资源数据,一旦令牌过时或失效便收回权限。
OAuth 2.0 规范中的令牌与小程序登陆场景下的 token 做用是一致的,只不过 OAuth 规范只定义了令牌的做用,并无限制它的具体使用方法,微信把 token 与 session_key 相关联,开发者服务器经过 token 取到 session_key 进而解密用户资源数据。
简单梳理一下,受权服务的核心就是,先颁发受权码 code 值,再颁发访问令牌 access_token 值。在颁发访问令牌的同时还会颁发刷新令牌 refresh_token 值,这种机制能够在无须用户参与的状况下用于生成新的访问令牌。正如咱们讲到的小明使用第三方软件玄武的例子,当访问令牌过时的时候,刷新令牌的存在能够大大提升小明使用第三方软件玄武的体验。
受权还要有受权范围,不能让第三方软件得到比注册时权限范围还大的受权,也不能得到超出了用户受权的权限范围,始终确保最小权限安全原则。好比,小明只为第三方软件玄武授予了获取当天订单的权限,那么第三方软件玄武就不能访问小明店铺里面的历史订单数据。
刷新令牌有过时时间吗,会一直有效吗?答案是刷新令牌也有有效期,若access_token未超时,那么进行refresh_token有两种方式,(1)不会改变access_token,但超时时间会刷新,至关于续期access_token(2)更新access_token的值,咱们建议【统一更新access_token的值】。
无限续期会增长access被破解的风险,延期access_token并非一个最好的方式,尽管有的开放平台是这么作的。不过当刷新令牌也过时了,只能从新登陆再受权。
在 OAuth 2.0 的体系里面有 4 种角色,按照官方的称呼它们分别是资源拥有者、客户端、受权服务和受保护资源。咱们不难发现,OAuth 2.0 受权的核心就是颁发访问令牌、使用访问令牌。 OAuth 2.0 的核心是受权许可,更进一步说就是令牌机制。也就是说,像第三方软件玄武这样的第三方软件只有拿到了微信商家开放平台颁发的访问令牌,也就是获得了受权许可,而后才能够表明用户访问他们的数据。
1.互联网中全部的受保护资源,几乎都是以 Web API 的形式来提供访问的,好比极客时间App 要获取用户的头像、昵称,第三方软件玄武要获取用户的店铺订单,咱们说OAuth 2.0 与安全相关,是用来保护 Web API 的。另外,第三方软件经过OAuth 2.0 取得访问权限以后,用户便把这些权限委托给了第三方软件,咱们说 OAuth 2.0 是一种委托协议,也没问题。
2.也正由于像玄武这样的第三方软件,每次都是用访问令牌而不是用户名和密码来请求用户的数据,才大大减小了安全风险上的“攻击面”。否则,咱们试想一下,每次都带着用户名和密码来访问数量众多的 Web API ,是否是增长了这个“攻击面”。所以,咱们说 OAuth 2.0 的核心,就是颁发访问令牌和使用访问令牌。
受权服务就是负责颁发访问令牌的服务。更进一步地讲,OAuth 2.0 的核心是受权服务,而受权服务的核心就是令牌。颁发受权码 code 的流程以下:
在这个过程当中,受权服务须要完成两部分工做,分别是准备工做和生成受权码 code。好比在点击微信小程序受权Button时,实际上已经作了一系列动做。包括验证基本信息、验证权限范围(第一次)和生成受权请求页面这三步等等。
验证基本信息,包括对第三方软件合法性和回调地址合法性的校验。在 Web 浏览器环境下发放 code 的整个请求过程,都是浏览器经过前端通讯来完成,这就意味着全部信息都有被冒充的风险。所以,受权服务必须对第三方软件的存在性作判断。一样,回调地址也是能够被伪造的。好比,不法分子将其假装成钓鱼页面,或者是带有恶意攻击性的软件下载页面。所以从安全上考虑,受权服务须要对回调地址作基本的校验。在受权服务的程序中,这两步验证经过后,就会生成或者响应一个页面(属于受权服务器上的页面),以提示用户进行受权。
既然是受权,就会涉及范围。好比,咱们使用微信登陆第三方软件的时候,会看到微信提示咱们,第三方软件能够得到你的昵称、头像、性别、地理位置等。若是你不想让第三方软件获取你的某个信息,那么能够不选择这一项。
这就意味着,咱们须要对第三方软件玄武传过来的 scope 参数,与第三方软件玄武注册时申请的权限范围作比对。若是请求过来的权限范围大于注册时的范围,就须要做出越权提示。记住,此刻是第一次权限校验。
当小程序或web页面出现不一样权限的button受权弹窗时,用户能够选择缩小这个权限范围,好比仅授予获取 地理位置或手机号 的权限。至此,颁发受权码 code 的准备工做就完成了。你要注意哈,我一直强调说这也是准备工做,由于当用户点击受权按钮“肯定”后,才会生成受权码 code 值和访问令牌acces_token 值,“一切才真正开始”。 在上面的准备过程当中,咱们忽略了小明登陆的过程,但只有用户登陆了才能够对第三方软件进行受权,受权服务才可以得到用户信息并最终生成 code 和app_id(第三方软件的应用标识) + user(资源拥有者标识)之间的对应关系。小明点击“赞成”按钮以后,生成受权码 code 的流程就正式开始了,主要包括验证权限范围(第二次)、处理受权请求生成受权码 code 和重定向至第三方软件这三大步。
在步骤二中,生成受权页面以前受权服务进行的第一次校验,是对比第三方软件玄武请求过来的权限范围 scope 和注册时的权限作的比对。这里为何又要校验一次呢?由于这至关于一次用户的输入权限。用户选择了必定的权限范围给到受权服务,对于权限的校验咱们要重视对待,凡是输入性数据都会涉及到合法性检查。另外,这也是要求咱们养成一种在服务端对输入数据的请求,都尽量作一次合法性校验的好习惯。
当用户赞成受权以后,受权服务会校验响应类型 response_type 的值。response_type 有code 和 token 两种类型的值。在这里,咱们是用受权码流程来举例的,所以代码要验证response_type 的值是否为 code。
在受权服务中,须要将生成的受权码 code 值与 app_id、user 进行关系映射。也就是说,一个受权码 code,表示某一个用户给某一个第三方软件进行受权,好比小明给第三方软件玄武进行的受权。同时,咱们须要将 code 值和这种映射关系保存起来,以便在生成访问令牌 access_token 时使用。
在生成了受权码 code 以后,咱们也按照上面所述绑定了响应的映射关系。这时,你还记得我以前讲到的受权码是临时的、一次性凭证吗?所以,咱们还须要为 code 设置一个有效期。 OAuth 2.0 规范建议受权码 code 值有效期为 10 分钟,而且一个受权码 code 只能被使用一次。不过根据经验呢,在生产环境中 code 的有效期通常不会超过 5 分钟。同时,受权服务还须要将生成的受权码 code 跟已经受权的权限范围 rscope 进行绑定并存储,以便后续颁发访问令牌时,咱们可以经过 code 值取出受权范围并与访问令牌绑定。由于第三方软件最终是经过访问令牌来请求受保护资源的。
生成受权码 code 值以后,受权服务须要将该 code 值告知第三方软件玄武。开始时咱们提到,颁发受权码 code 是经过前端通讯完成的,所以这里采用重定向的方式。到此,颁发受权码 code 的流程所有完成。当第三方软件玄武获取到受权码 code 值之后,就能够开始请求访问令牌 access_token 的值。
当第三方软件玄武拿着受权码 code 来请求的时候,受权服务须要为之生成最终的请求访问令牌。这个过程主要包括验证第三方软件是否存在、验证 code 值是否合法和生成 access_token 值这三大步。
此时,接收到的 grant_type 的类型为 authorization_code。因为颁发访问令牌是经过后端通讯完成的,因此这里除了要校验 app_id 外,还要校验 app_secret。
String grantType = request.getParameter("grant_type");
if("authorization_code".equals(grantType)){
}
if (!appMap.get("app_id").equals(appId)) {
//app_id不存在
}
if (!appMap.get("app_secret").equals(appSecret)) {
//app_secret不合法
}
复制代码
受权服务在颁发受权码 code 的阶段已经将 code 值存储了起来,此时对比从 request 中 接收到的 code 值和从存储中取出来的 code 值。这里咱们必定要记住,确认过受权码 code 值有效之后,应该马上从存储中删除当前的 code 值,以防止第三方软件恶意使用一个失窃的受权码 code 值来请求受权服务。
关于按照什么规则来生成访问令牌 access_token 的值,OAuth 2.0 规范中并无明确规定,但必须符合三个原则:惟一性、不连续性、不可猜性。和受权码 code 值同样,咱们须要将访问令牌 access_token 值存储起来,并将其与第三方软件的应用标识 app_id 和资源拥有者标识 user 进行关系映射。也就是说,一个访问令牌 access_token 表示某一个用户给某一个第三方软件进行受权。 同时,受权服务还须要将受权范围跟访问令牌 access_token 作绑定。最后,还须要为该访问令牌设置一个过时时间 expires_in,好比 1 天。
正由于 OAuth 2.0 规范没有约束访问令牌内容的生成规则,因此咱们有更高的自由度。咱们既能够像 Demo 中那样生成一个 UUID 形式的数据存储起来,让受权服务和受保护资源共享该数据;也能够将一些必要的信息经过结构化的处理放入令牌自己。咱们将包含了一些信息的令牌,称为结构化令牌,简称 JWT。
至此,受权码许可类型下受权服务的两大主要过程,也就是颁发受权码和颁发访问令牌的流程。接下来,你在分析微信登陆的第三方软件的时候,就会明白很快背后的原理了。同时,你在本身搭建一个受权服务流程时,也会更加驾轻就熟。这一切的缘由,都在于颁发受权码和颁发访问令牌,就是受权服务的核心。
为何必定要引入刷新令牌的概念。好比用户给微信小程序某电商应用受权之后,正在愉快地处理他的双十一的订单数据,结果没过多久,忽然间受权过时,第三方电商应用再次让用户进行受权。此刻用户的体验是很是糟糕的。为此,OAuth 2.0 中引入了刷新令牌的概念,也就是刷新访问令牌 access_token 的值。这就意味着,有了刷新令牌,用户在必定期限内无需从新点击受权按钮,就能够继续使用第三方软件。
刷新令牌也是给第三方软件使用的,一样须要遵循先颁发再使用的原则。所以,咱们仍是从颁发和使用两个环节来学习刷新令牌。
其实,颁发刷新令牌和颁发访问令牌是一块儿实现的,都是在过程二的步骤三生成访问令牌access_token 中生成的。也就是说,第三方软件获得一个访问令牌的同时,也会获得一个刷新令牌。 看到这里你可能要问了,为何要一块儿生成访问令牌和刷新令牌呢?
其实,这就回到了刷新令牌的做用上了。刷新令牌存在的初衷是,在访问令牌失效的状况下,为了避免让用户频繁手动受权,用来经过系统从新请求生成一个新的访问令牌。那么,若是访问令牌失效了,而“身边”又没有一个刷新令牌可用,岂不是又要麻烦用户进行手动受权了。因此,它必须得和访问令牌一块儿生成。
在 OAuth 2.0 规范中,刷新令牌是一种特殊的受权许可类型,是嵌入在受权码许可类型下的一种特殊许可类型。在受权服务的代码里,当咱们接收到这种受权许可请求的时候,会先比较 grant_type 和 refresh_token 的值,而后作下一步处理。
此时请求中的 grant_type 值为 refresh_token。和颁发访问令牌前的验证流程同样,这里咱们也须要验证第三方软件是否存在。须要注意的是,这里须要同时验证刷新令牌是否存在,目的就是要保证传过来的刷新令牌的合法性。
另外,咱们还须要验证刷新令牌是否属于该第三方软件。受权服务是将颁发的刷新令牌与第三方软件、当时的受权用户绑定在一块儿的,所以这里须要判断该刷新令牌的归属合法性。 须要注意,一个刷新令牌被使用之后,受权服务须要将其废弃,并从新颁发一个刷新令牌。
生成访问令牌的处理流程,与颁发访问令牌环节的生成流程是一致的。受权服务会将新的访问令牌和新的刷新令牌,一块儿返回给第三方软件。 不少电商小程序都会设置token失效自动刷新请求,作法以下:
/** 刷新Token, 默认只刷新一次 */
function refreshToken(params: AxiosRequestConfig) {
return promisify(wx.login)()
.then((res: WechatMiniprogram.LoginSuccessCallbackResult) => promisify(wx.request)({
url: config.loginUrl + res.code
}))
.then((res: any) => {
wx.setStorageSync('token', res.data.jwtString)
return refreshRequest(params)
}, (err: any) => {
return Promise.reject(err)
})
}
/** 从新发起请求 */
function refreshRequest(config: AxiosRequestConfig) {
return promisify(wx.request)({
url: config.url,
header: Object.assign({}, config.headers, {
'Authorization': wx.getStorageSync('token')
}),
data: config.data,
method: config.method,
timeout: config.timeout
}).then((res: any) => {
const response: AxiosResponse = {
data: res.data,
status: res.statusCode,
statusText: res.errMsg,
headers: res.header,
config: config,
cookies: res.cookies
}
return response
}, (err: any) => {
return Promise.reject(err)
})
}
复制代码
受权码许可流程有两种通讯方式。一种是前端通讯,由于它经过浏览器促成了受权码的交互流程,好比微信商家开放平台的受权服务生成受权码发送到浏览器,第三方软件玄武从浏览器获取受权码。正由于获取受权码的时候第三方软件玄武和受权服务并无发生直接的联系,也叫作间接通讯。另一种是后端通讯,在第三方软件玄武获取到受权码以后,在后端服务直接发起换取访问令牌的请求,也叫作直接通讯。 为何要用受权码换取token,而不是直接获取token?
直接获取token的场景是有的,客户端凭据许可类型就是这样的使用场景,受权码许可类型是OAuth 2.0 最安全 最完备的许可类型。 以Web场景为例,第一次用户是跟第三方软件创建的“联系”,三方软件要把用户引导到平台一方去受权,这个时候用户实际上跟三方软件就失去了“联系”,平台若是这个时候直接把令牌给了三方软件,由于没了“联系”,三方软件就不能很方便的告诉用户。
在 OAuth 2.0 中,访问令牌被要求有极高的安全保密性,所以咱们不能让它暴露在浏览器上面,只能经过第三方软件(好比玄武)的后端服务来获取和使用,以最大限度地保障访问令牌的安全性。正由于访问令牌的这种安全要求特性,当须要前端通讯,好比浏览器上面的流转的时候,OAuth 2.0 才又提供了一个临时的凭证:受权码。经过受权码的方式,可让用户小明在受权服务上给第三方软件玄武受权以后,还能从新回到第三方软件玄武的操做页面上。
从受权码许可流程中就能够看出来,它完美地将 OAuth 2.0 的 4 个角色组织了起来,并保证了它们之间的顺畅通讯。它提出的这种结构和思想均可以被迁移到其余环境或者协议上,好比在微信小程序中使用受权码许可。
不过,也正是由于有了受权码的参与,才使得受权码许可要比其余受权许可类型,在受权的流程上多出了好多步骤,让受权码许可类型成为了 OAuth 2.0 体系中迄今流程最完备、安全性最高的受权流程。
《OAuth 2.0实战课》王新栋老师
《云原生微信小程序开发实战》周俊鹏