3、OAuth2.0授权机制:企业微信OAuth2.0流程详解
说到OAuth2.0,很多刚接触企业微信开发的朋友会觉得有点绕。其实说白了,它就是一套「通行证」机制。你想想看,用户不可能每次都把密码告诉你的应用,那太危险了。OAuth2.0就是让用户授权给你的应用,去访问他在企业微信里的部分信息。
我个人习惯把OAuth2.0理解成「酒店房卡」——用户在前台(企业微信)办入住,拿到一张房卡(code),然后凭这张卡去开门(获取成员信息)。整个过程不需要用户把身份证押在你这里。
3.1 企业微信OAuth2.0流程全景
整个流程分三步走,我画个简图给你看:
用户点击应用 → 跳转企业微信授权页 → 获取code
↓
用code换取access_token → 用access_token获取成员信息
↓
完成身份认证,进入业务系统
嗯,这里要注意一个关键点:企业微信的OAuth2.0和微信公众平台的不太一样。企业微信的授权是「静默」和「手动」两种模式。我在项目中遇到过,很多新手把这两种模式搞混,结果授权页面死活弹不出来。
3.2 获取code:第一步也是最重要的一步
获取code是整个流程的入口。你需要构造一个URL,让用户跳转到企业微信的授权页面。
URL格式长这样:
https://open.weixin.qq.com/connect/oauth2/authorize?
appid=CORPID
&redirect_uri=REDIRECT_URI
&response_type=code
&scope=snsapi_base
&state=STATE
#wechat_redirect
这里有几个参数我重点说一下:
- appid:你的企业ID,在管理后台「我的企业」里能找到。我建议你把它配在配置文件里,别硬编码。
- redirect_uri:回调地址,需要URL编码。我曾经踩过一个坑——回调地址没在管理后台配置白名单,结果一直报redirect_uri错误。
- scope:授权范围。snsapi_base是静默授权,用户无感知;snsapi_userinfo是手动授权,会弹确认框。
- state:防跨站攻击的参数。我个人习惯用随机字符串+时间戳,回调时校验一下。
3.3 通过code获取成员信息
拿到code之后,就该用它换成员信息了。这里需要调用企业微信的API:
GET https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?
access_token=ACCESS_TOKEN
&code=CODE
返回的数据结构大概是这样的:
{
"errcode": 0,
"errmsg": "ok",
"UserId": "zhangsan",
"DeviceId": "xxxxxxxx",
"user_ticket": "xxxxxxxx"
}
这里有个细节:如果用户是企业外部联系人,返回的是OpenId而不是UserId。我在做客户管理系统时就遇到过这个情况,内外部的处理逻辑完全不一样。
3.4 access_token的管理与刷新
access_token是企业微信API的「万能钥匙」。几乎所有接口都需要它。但它的有效期只有7200秒(2小时),过期了就得重新获取。
获取access_token的接口很简单:
GET https://qyapi.weixin.qq.com/cgi-bin/gettoken?
corpid=ID
&corpsecret=SECRET
返回结果:
{
"errcode": 0,
"errmsg": "ok",
"access_token": "xxxxxx",
"expires_in": 7200
}
嗯,这里我要重点说说管理策略。我见过太多人每次调用API都去获取一次access_token,这其实很浪费。正确的做法是:
- 缓存起来:用Redis或者本地文件存起来,别每次都请求。
- 提前刷新:我习惯在过期前10分钟就刷新,避免临界点问题。
- 加锁处理:高并发场景下,多个请求同时发现token过期,会同时去刷新。这时候需要加分布式锁。
刷新策略的伪代码我写一下:
function getAccessToken() {
// 先从缓存取
token = redis.get("qywx_access_token")
if (token != null) {
return token
}
// 加锁,防止并发刷新
lock = redis.lock("qywx_token_lock", 10)
if (lock) {
// 双重检查
token = redis.get("qywx_access_token")
if (token == null) {
// 调用API获取新token
token = fetchTokenFromAPI()
// 设置缓存,过期时间设为7100秒(留100秒缓冲)
redis.set("qywx_access_token", token, 7100)
}
redis.unlock(lock)
}
return token
}
3.5 完整流程串联
把上面这些串起来,一个完整的OAuth2.0认证流程大概是这样的:
- 用户访问你的应用,你检测到未登录
- 构造授权URL,让用户跳转到企业微信
- 用户授权后,企业微信回调你的redirect_uri,带上code和state
- 你校验state,然后用code换取用户信息
- 根据UserId创建或更新本地用户会话
- 用户登录成功,进入业务系统
说起来简单,但实际落地时坑不少。我建议你先把流程图画清楚,再动手写代码。尤其是异常处理——用户取消授权怎么办?code过期怎么办?这些都要想好。