OAuth2.0 实现流程详解:从登录授权到接口调用

最近公司新上线了一个内部管理系统,前端同事提了个需求:用户想用微信账号直接登录。这事儿交到了我手上,得上 OAuth2.0。很多人一听这词觉得高大上,其实拆开来看,就是一套标准的“代买奶茶”流程——你不想把密码交给别人,又想让他帮你完成操作。

四个角色先搞清

OAuth2.0 里有四个关键角色:资源所有者(就是用户)、客户端(你的应用)、授权服务器(比如微信的登录接口)、资源服务器(存放用户数据的地方)。拿微信登录来说,你想让系统获取你的昵称头像,但又不想把微信账号密码输在我们这系统里,这时候就得靠授权服务器来“中间传话”。

授权码模式最常用

目前最安全也最常用的流程是“授权码模式”(Authorization Code Flow)。整个过程分几步走:

第一步,你的浏览器被重定向到微信的授权页面,URL 长这样:

https://open.weixin.qq.com/connect/qrconnect?appid=YOUR_APPID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=snsapi_login&state=abc123

其中 redirect_uri 是回调地址,state 是防CSRF攻击的随机值。用户扫码确认后,微信会把浏览器跳回你指定的 redirect_uri,并带上一个 code 参数,比如:

https://your-system.com/callback?code=AUTHORIZATION_CODE&state=abc123

这个 code 只能用一次,有效期很短,不能用来直接拿数据,只是个“取货凭证”。

服务端换令牌才是正经事

接下来,你的服务器要拿着这个 code,加上自己的 appid 和 appsecret,去微信服务器请求真正的 access_token。这一步必须在服务端完成,不能放在前端,不然 secret 就暴露了。

POST https://api.weixin.qq.com/sns/oauth2/access_token
Content-Type: application/x-www-form-urlencoded

appid=YOUR_APPID&secret=YOUR_SECRET&code=AUTHORIZATION_CODE&grant_type=authorization_code

微信验证通过后,会返回 JSON 数据:

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

有了 access_token 和 openid,你就可以调用

GET https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

拿到用户的昵称、头像、性别等信息,完成登录态绑定。

刷新令牌延长使用周期

access_token 一般两小时过期,但你总不能让用户每两小时重新登录一次。这时候 refresh_token 就派上用场了。当 token 过期时,可以用 refresh_token 去申请新的 access_token,而不需要用户再次授权。

POST https://api.weixin.qq.com/sns/oauth2/refresh_token

appid=YOUR_APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

当然,refresh_token 也不是永久有效的,通常能用30天,过期就得重新走完整流程。

实际部署要注意的事

上线前做了次压测,发现并发请求同一个 code 换 token 会失败。后来加了层缓存,确保每个 code 只处理一次。另外,redirect_uri 一定要精确匹配,带不带斜杠都得对上,不然微信直接拒掉。

还有个小坑:本地调试时用 localhost,但微信后台不认。我们临时搭了个内网穿透,用 ngrok 映射出一个公网地址,才顺利跑通全流程。

现在这套流程跑得挺稳,每天几百人用微信登录,没再为账号问题来找过运维。说到底,OAuth2.0 不是啥黑科技,就是一套大家约定好的“信任传递”规则,用好了,省事又安全。