介绍
目前有很多网站需要对接微信oauth认证登录,简单叙述一下整个流程
流程
-
申请测试号
-
填写测试号信息(重点解释回调url)
-
后端生成链接(提供给前端网页生成二维码)
-
前端生成二维码并轮训
-
用户扫码
-
后端处理微信回调
-
轮训查询到用户认证成功
参考
微信的官方文档
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
Step1 申请测试号
前往微信的官方文档,申请测试号 网页地址https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
开发指南-->接口测试号申请
微信扫描一下就可以了
Step2 填写测试信息
说明:因为本篇文章主要阐述微信授权网页登陆的流程,所以申请的测试号,如果已经有公众号、可以进入公众号进行配置,针对测试号,微信是允许用IP,不一定需要ICP备案过的域名,本文中提到的所有ip如果你有备案号的域名也可以直接使用
appId和appSecret 用户调用微信接口的时候传给微信,需要保存好
js 安全域名就是你的服务器的IP地址
接口配置信息里面的
Url
url : 当用户发生扫码、关注公众号等行为微信会推送信息给你的服务器,这里的url就是你的服务器url
几个关键点
-
你的服务器必须部署在公网,这里的URL必须是公网IP或者域名 如http://116.116.116.116/wechat/callback
-
由于是测试号所以你的IP可以是裸IP,但是你的端口号必须是80/443
-
在配置之前必须部署好这个接口并认证
/**
* 认证方式
* 第一次微信请求的时候会调用get并且带一个echostr参数
* 你需要原封不动返回这个参数给微信,才算微信接入成功,以koa为例
* 微信调用的url是 http://ip/xxx?signature=xxx×tamp=xxx&nonce=xx&echostr=xxxx
* 这里我就不展示从url里面获取echostr了
*/
router.get('/xxxxx',ctx=>{
ctx.body = echostr
})
-
用户不同的行为微信调用的时候会用不同的Method,比如用户通过微信网页开发-->网页授权回调就是GET,比如账号管理-->生成带参数的二维码微信回调就是POST
token
token用于判断回调是否真的来自于微信
参数 | 描述 |
---|---|
signature | 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 |
nonce | 随机数 |
echostr | 随机字符串 |
加密/校验流程如下
-
将token、timestamp、nonce三个参数进行字典序排序
-
将三个参数字符串拼接成一个字符串进行sha1加密
-
开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
遇到的坑
在微信的OAuth2.0认证中,一直无法配置成功,原来需要在体验接口权限表-->网页服务--> 网页账号 点击右边的修改 输入服务器的ip地址 如 116.116.116.116
Step3 后端生成链接
思路主要是后端生成一个链接地址给前端网页(网页展示给用户后带着后端给的key去轮询查询后端用户的状态),然后用户用微信扫描,然后用户确认信息后微信服务器推送信息,我们的服务器收到推送保存数据,前端请求到数据后改变页面信息
前端发出http请求,下面的代码主要展示的是后端处理生成图片链接,这里需要调用微信的接口生成url,记得返回直接urldecode一下
url里面的token是你的服务器和微信服务器之间通信的凭证,有有效期以及每日调用次数的上限,需要后端自己维护
const getQrcodeUrl = `https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${token}`
const ticket = await axios.post(getQrcodeUrl, {
expire_seconds: 604800, //超时时间
action_name: 'QR_STR_SCENE', //固定
action_info: {
scene: {
scene_id: 123, //场景id :根据业务需求自定义 可以识别用户是通过那种场景进入的微信公众号
scene_str: key //key : 根据自己的业务需求定义 后面微信推送信息会把这个信息推送给你的服务器
}
}
})
if (!ticket.data.ticket) {
throw `获取二维码票据失败`
}
return ctx.body = {
success: true,
data: {
ticket: urlencode(ticket.data.ticket),
key: key
}
}
Step4 前端生成二维码并轮训
前端请求收到后端的返回后, 用image标签展示给用户
<image src='xxxxx' />
上面后端给前端返回了一个key 前端拿着这个key去轮训查看后端的状态,如果用户扫码微信推送状态后,拿着这个key去请求的接口里面就可以返回 登录成功以及服务器的一些凭证 jwt之类的 然后我们去做对应的业务处理(跳转、等)
注意 如果是轮训请求后端接口 处理成功后记得清除定时器
Step5 用户使用手机微信扫码
Step6 后端处理微信回调
当用户扫码后微信会推送信息给你的服务器,地址就是你上面注册的回调地址,比如http://116.116.116.116/wechat/callback,微信推送的payload body的信息格式是 xml 如果需要解析成json 可以使用一些第三方的库,比如xml2js
bash | npm install xml2js
当用户扫码后微信会推送信息给你的服务器,地址就是你上面注册的回调地址,比如http://116.116.116.116/wechat/callback,微信推送的payload body的信息格式是 xml 如果需要解析成json 可以使用一些第三方的库,比如xml2js
解析后的数据能提取到key,根据key去修改数据的状态,认为这次的认证已经完成
Step7 轮训查询到用户认证成功
前端根据key轮训请求后端的接口返回值对应的修改 前端获取到用户已经认证成功后可以继续处理业务,比如登录成功、跳转之类的