2、授权机制详解:OAuth2.0授权流程、授权码获取、access_token与refresh_token、预授权码(pre_auth_code)机制

好,咱们直接进入正题。授权机制,说白了就是微信开放平台第三方应用的核心命脉。你想想看,如果没有这套机制,第三方应用怎么能安全地替用户操作公众号、小程序?

我个人习惯把OAuth2.0比作「门禁卡系统」。用户是访客,第三方应用是快递员,微信开放平台就是那个保安。快递员想进楼,得先让访客授权,保安再给一张临时门禁卡。嗯,这个比喻虽然糙,但理不糙。

2.1 OAuth2.0授权流程:三步走

微信开放平台的OAuth2.0授权,说白了就是三步:

  1. 引导用户去授权页面 —— 让用户点击一个链接,跳转到微信的授权页面。
  2. 用户同意后,拿到授权码(code) —— 微信回调你的服务器,带上一个临时凭证。
  3. 用授权码换令牌(access_token) —— 你的后台拿着code去微信服务器换真正的通行证。

我在项目中遇到过不少新手,第一步就搞错了。他们以为授权码是用户手动输入的,其实不是。授权码是微信服务器通过回调地址自动传给你的。你只需要在回调URL里接收一个叫 code 的参数就行。

核心要点: 授权码是一次性的,有效期只有5分钟。拿到后要立刻换access_token,别磨蹭。

2.2 授权码获取:细节决定成败

获取授权码的URL长这样:

https://open.weixin.qq.com/connect/oauth2/authorize?
  appid=APPID
  &redirect_uri=REDIRECT_URI
  &response_type=code
  &scope=SCOPE
  &state=STATE
  #wechat_redirect

这里有几个坑,我一个个说。

第一个坑:redirect_uri 必须做URL编码。 我曾经有个同事,直接把带中文的URL扔进去,结果回调死活收不到code。后来发现是没编码。记住,用 encodeURIComponent 处理一下。

第二个坑:state参数一定要用。 很多人觉得state是多余的,其实它是防CSRF攻击的关键。你生成一个随机字符串,存到session里,回调时比对一下。不一致就拒绝。嗯,这个习惯我从入行第一天就养成了。

第三个坑:scope的选择。 微信提供了两种scope:

scope值 说明 适用场景
snsapi_base 静默授权,不弹出授权页面 只需要openid的场景
snsapi_userinfo 弹出授权页面,需要用户确认 需要获取用户昵称、头像等

你想想看,如果只是识别用户身份,用 snsapi_base 就够了。别动不动就弹授权框,用户体验会变差。我一般这样设计:首页用静默授权,只有需要用户信息时才弹框。

2.3 access_token与refresh_token:双令牌机制

拿到授权码后,就该换access_token了。接口是这样的:

https://api.weixin.qq.com/sns/oauth2/access_token?
  appid=APPID
  &secret=SECRET
  &code=CODE
  &grant_type=authorization_code

返回的数据结构:

{
  "access_token": "ACCESS_TOKEN",
  "expires_in": 7200,
  "refresh_token": "REFRESH_TOKEN",
  "openid": "OPENID",
  "scope": "SCOPE"
}

这里要注意,access_token的有效期只有2小时。过期了怎么办?用refresh_token去换新的。

我的经验: refresh_token的有效期是30天。但如果你在30天内没用它,它也会过期。所以建议在access_token过期前,提前用refresh_token刷新。我一般设置一个定时任务,每1小时检查一次token的剩余有效期。

刷新access_token的接口:

https://api.weixin.qq.com/sns/oauth2/refresh_token?
  appid=APPID
  &grant_type=refresh_token
  &refresh_token=REFRESH_TOKEN

警告: 每次刷新后,微信会返回一个新的refresh_token。旧的会失效。所以一定要把新的refresh_token存起来。我曾经见过有人忘了更新,结果第二天所有用户都掉线了。

2.4 预授权码(pre_auth_code)机制:第三方应用的专属凭证

前面说的都是针对单个用户的授权。但作为第三方应用,你还需要一个「预授权码」来代表你的应用本身。这个预授权码,说白了就是你的应用向微信服务器申请的一个临时凭证,用来发起授权流程。

获取预授权码的接口:

POST https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?
  component_access_token=COMPONENT_ACCESS_TOKEN

{
  "component_appid": "COMPONENT_APPID"
}

返回:

{
  "pre_auth_code": "PRE_AUTH_CODE",
  "expires_in": 600
}

预授权码的有效期只有10分钟。为什么这么短?因为它是用来发起授权流程的,用完就废。你想想看,如果有效期太长,万一泄露了,别人就能冒充你的应用去授权。

我在项目中遇到过一个问题:预授权码用完后,需要重新获取。但获取预授权码又需要component_access_token。而component_access_token的有效期也是2小时。所以你需要一套完整的令牌管理机制。

避坑指南: 我曾经在预授权码上栽过跟头。当时没注意有效期,把预授权码存到了数据库里,结果用户点击授权时,预授权码已经过期了。后来我改成「按需获取」,每次发起授权前实时请求一个新的预授权码。问题就解决了。

预授权码的使用场景是这样的:

  1. 你的后台获取一个预授权码。
  2. 拼接授权链接,让用户点击。
  3. 用户同意后,微信回调你的服务器,带上授权码。
  4. 你用授权码去换公众号/小程序的access_token。

嗯,到这里,授权机制的核心内容就讲完了。总结一下:

  • OAuth2.0 是基础,三步走:引导授权 → 拿code → 换token。
  • access_token 是短期令牌,2小时过期,用refresh_token刷新。
  • 预授权码 是第三方应用的临时凭证,10分钟有效,按需获取。

下一章,我会讲如何用这些令牌去调用微信的API。到时候你会发现,令牌管理才是真正的重头戏。