
1.2.2 授权码授权模式
1.授权请求示例
授权码授权(Authorization Code Grant)模式是一种应用广泛、安全可靠的授权模式,前期的授权流程类似隐式授权模式,不同之处在于授权码授权模式不再直接返回access_token,而是返回有效期较短的code。第三方应用在获取code的请求后,在后台使用code、client_id和client_secret,通过HttpClient发起post请求,从而获取一个内容丰富的token。具体的授权流程如下。
步骤1 获取code的请求,如示例1.3所示。

示例1.3 获取code的请求
示例1.3中各参数的含义如下。
• client_id:第三方应用在开放平台注册完成后获取的唯一标识。
• response_type:在授权码授权模式中,该参数的值为code。
• redirect_url:第三方应用在开放平台注册的回调地址。
• state:由第三方应用指定,当授权系统回调到第三方应用时,会在回调请求中携带该参数值。在回调到第三方应用时,授权系统会原封不动地将第三方应用传递的state参数回传给第三方应用。
提示
第三方应用通常使用state参数进行校验或幂等操作。
• scope:第三方应用的访问权限,一般由逗号分隔的多个字符串组成。
步骤2 假设回调地址为https://example.com/callback,第三方应用在引导用户访问示例1.3后,会跳转到登录页面。在用户登录成功后,授权系统会生成code,并通过预设的回调地址回调到第三方应用。示例1.4所示为code回调请求示例。

示例1.4 code回调请求示例
示例1.4中各参数的含义如下。
• https://example.com/callback:第三方应用预设的回调地址,授权系统会直接回调到该地址。
• state:在步骤1中由第三方应用传入的参数,在回调到第三方应用时会原封不动地回传。
• code:步骤1 请求的目标结果。第三方应用将使用code换取用户授权的access_token。
步骤3 第三方应用在获取code后,会在程序后台通过HttpClient,主动发起请求,获取用户授权的access_token。第三方应用创建的access_token请求如示例1.5所示。

示例1.5 access_token请求
示例1.5中各参数的含义如下。
• client_id:第三方应用在开放平台注册完成后获取的唯一标识。
• client_secret:第三方应用在开放平台注册完成后获取的密码。
• code:步骤2中获取的code回调请求。
• grant_type:OAuth 2规定在授权码授权模式下,该字段的值为authorization_code。授权系统会根据该字段进行授权模式区分,即授权系统会根据该字段识别到当前模式为授权码授权模式,从而执行该模式下必要参数的校验和授权逻辑。
步骤4 授权系统收到请求并进行验证,在验证通过后,会返回如示例1.6所示的授权信息给第三方应用。

示例1.6 授权信息
示例1.6中各参数的含义如下。
• access_token:访问令牌,是用户授权的唯一凭证。使用此令牌访问开放平台的网关,从而获取数据或调用功能。
• expires_in:token的过期时间,单位为秒。
• refresh_token:刷新token,可对access_token进行续期。
• refresh_expires_in:刷新token的有效时间,单位为秒。
• open_id:用户在第三方应用的唯一标识。
• scope:第三方应用的访问权限,一般由逗号分隔的多个字符串组成。
• token_type:access_token的类型。
步骤5 第三方应用在获取信息后,首先根据open_id将用户绑定到系统中,然后使用refresh_token刷新access_token的有效期。这是因为open_id可用于识别用户并保存相关信息,access_token可调用用户在开放平台的相关资源。
由于第三方应用有刷新access_token的需求,因此在授权码授权模式下,授权系统为第三方应用提供刷新access_token的接口。刷新授权信息请求如示例1.7所示。

示例1.7 刷新授权信息请求
示例1.7中各参数的含义如下。
• client_id:第三方应用在开放平台注册完成后获取的唯一标识。
• client_secret:第三方应用在开放平台注册完成后获取的密码。
• grant_type:在刷新access_token时,该字段的值为refresh_token,开放平台会根据该字段识别出当前第三方应用正在发起刷新access_token请求,从而进行刷新access_token时的必要参数校验,并在校验通过后执行刷新access_token的具体逻辑。
• refresh_token:示例1.6中获取的refresh_token。
第三方应用发起示例1.7的请求后,会得到与示例1.6类似的授权信息,不过返回的内容会不同,即可能生成新的access_token或使用原来的token。不同的系统会有不同的策略,在后续章节中再继续讨论。
2.系统交互流程
前文通过获取code、获取授权信息和刷新授权信息这3个子流程介绍了授权的完整生命周期。授权码授权模式的流程如图1-2所示。
步骤1 用户访问第三方应用。
步骤2 第三方应用引导用户向授权系统发起获取code的请求。
步骤3 首先授权系统进行初步校验,校验参数是否合法,如client_id是否存在,redirect_url是否一致等;然后重定向到认证系统,发起用户认证。
步骤4 用户在认证系统中进行登录,登录成功后认证系统会回调到授权系统。授权系统在获取用户信息、进行必要的授权流程后生成access_token。

图1-2 授权码授权模式的流程
步骤5 授权系统重定向到第三方应用的回调地址。
步骤6 第三方应用在后台使用code换取用户授权的access_token。
步骤7 授权系统返回完整的授权信息。
提示
自此已获取用户授权的access_token信息,用户可以调用相关接口实现相关业务。后续步骤为第三方应用通过刷新access_token来维持access_token的有效性。
步骤8 使用refresh_token刷新token。
步骤9 授权系统向第三方应用返回完整的授权信息。
总结
授权码授权模式是在实际工作中应用最多的授权模式,有如下优点。
• 可灵活设置access_token的过期时间,第三方应用可以根据需求来刷新access_token的过期时间,从而满足不同的业务需求。access_token的有效期越长,对第三方应用的负担越轻,同时安全性也越低。反之,access_token的有效期越短,对第三方应用的负担越重,同时安全性也越高。详细内容在后文中有相关介绍。
• access_token是第三方应用通过后端通道请求获取的,不会展示在浏览器上。授权系统可以设置https服务,第三方应用会强制使用https获取access_token,确保信息不被拦截。
• code会展示在浏览器的URL中(见示例1.4),这样就把code暴露在了用户可见的前端通道中,但code有效期短且只能使用一次,因此code需要配合client_secret(第三方应用密码,不会泄露给任何人)才能使用,确保了只有第三方应用才能使用code获取授权信息。