2、授权机制详解:OAuth2.0授权流程、授权码获取、access_token与refresh_token、预授权码(pre_auth_code)机制
好,咱们直接进入正题。授权机制,说白了就是微信开放平台第三方应用的核心命脉。你想想看,如果没有这套机制,第三方应用怎么能安全地替用户操作公众号、小程序?
我个人习惯把OAuth2.0比作「门禁卡系统」。用户是访客,第三方应用是快递员,微信开放平台就是那个保安。快递员想进楼,得先让访客授权,保安再给一张临时门禁卡。嗯,这个比喻虽然糙,但理不糙。
2.1 OAuth2.0授权流程:三步走
微信开放平台的OAuth2.0授权,说白了就是三步:
- 引导用户去授权页面 —— 让用户点击一个链接,跳转到微信的授权页面。
- 用户同意后,拿到授权码(code) —— 微信回调你的服务器,带上一个临时凭证。
- 用授权码换令牌(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小时。所以你需要一套完整的令牌管理机制。
避坑指南: 我曾经在预授权码上栽过跟头。当时没注意有效期,把预授权码存到了数据库里,结果用户点击授权时,预授权码已经过期了。后来我改成「按需获取」,每次发起授权前实时请求一个新的预授权码。问题就解决了。
预授权码的使用场景是这样的:
- 你的后台获取一个预授权码。
- 拼接授权链接,让用户点击。
- 用户同意后,微信回调你的服务器,带上授权码。
- 你用授权码去换公众号/小程序的access_token。
嗯,到这里,授权机制的核心内容就讲完了。总结一下:
- OAuth2.0 是基础,三步走:引导授权 → 拿code → 换token。
- access_token 是短期令牌,2小时过期,用refresh_token刷新。
- 预授权码 是第三方应用的临时凭证,10分钟有效,按需获取。
下一章,我会讲如何用这些令牌去调用微信的API。到时候你会发现,令牌管理才是真正的重头戏。