网页授权微信登陆

516 阅读5分钟

介绍

目前有很多网站需要对接微信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&timestamp=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轮训请求后端的接口返回值对应的修改 前端获取到用户已经认证成功后可以继续处理业务,比如登录成功、跳转之类的