H5及web页面微信授权登录流程

PC端微信扫码登录流程:

为什么要微信登录:

如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。微信拥有庞大且稳定活跃的用户基数,直接将我们的app接入到微信的生态可以免去复杂的新用户注册流程,使用户体验更良好。

微信登录的几种情况:
  • PC端:

    • PC端微信浏览器 -> 直接调用微信授权(不扫码,使用微信服务号的appid和appsecret)

    • PC端其他浏览器 -> 跳转微信的扫码登录页面(需要扫码,使用微信开放平台注册的PC应用appid和appsecret)

  • 移动端:

    • 微信客户端打开 -> 直接调用微信授权(不扫码,使用微信服务号的appid和appsecret)

    • 其他手机浏览器打开 -> 跳转微信的扫码登录页面(需要扫码,使用微信开放平台注册的PC应用appid和appsecret)

区分是否是PC环境的方法:

判断是PC环境还是移动环境是为了相应切换应用的布局,目前采用css媒体查询来做判断:

/* 屏幕宽度小于等于1070像素时识别为移动端(1070像素是使推荐页常用情报站栏不现实滚动条的最小宽度) */
@media screen and (max-width: 1070px) {
    /* 移动端布局css样式 */
}
/* 屏幕宽度大于1071像素识别为PC端 */
@media screen and (min-width: 1071px) {
    /* PC端布局样式 */
}

这里目前的设计是将判断UI样式和判断登录逻辑区分开的,两个功能分别独立判断

区分微信登录的几种情况的方法:
  • 前端在登录时获取用户设备信息(userAgent)
let UA = navigator.userAgent.toLocaleLowerCase()  
// UA的格式可能因设备不同而采用不同的大小写格式这里我们先统一为小写方便下一步判断
UA.indexOf("micromessenger") != -1
// 通过indexOf方法来判断字符串里是否有要查询的字段

前端操作

1 获取code(此步骤由前端完成)
  • 首先要在微信开放平台里申请创建一个web应用,填写完基本信息之后提交审核,最长7个工作日,一般两天就能下来。审核通过以后可以得到web应用的AppID和AppSecret,稍后请求微信登录的二维码。

  • 在得到web应用的AppID以后前端需要配置请求登录二维码的url:

// 前端使用appid和回调域名来获取微信登陆二维码

window.location.replace(
    "https://open.weixin.qq.com/connect/qrconnect?" +
    "appid=" + APP_id + "&" +
    "redirect_uri=" + encodeURIComponent('http://wx.digitwonder.com') + "&" +
    "scope=snsapi_login#wechat_redirect" )

这个配置中AppID字段是向后台传微信开放平台的web应用AppID,回调地址也是在开放平台注册时留的地址,而且这个回调地址的uri需要经过encode编码加密以后拼接到请求的。'scope'字段表示请求的作用域,微信扫码登录时scope字段固定写'snsapi_login'。将这个地址拼接好以后就可以将路由定向到微信的二维码页面了。

参数说明
参数 是否必须 说明
appid 应用唯一标识(前面认证网页应用中获得)
redirect_uri 重定向地址,需要进行UrlEncode(前面认证网页应用中获得)
response_type 填code
scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可
state 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
  • 在页面定位到微信二维码页面以后扫码确认,页面会被定向到之前配置的回调页面地址并且将请求来的code拼接到url上一并返回,我们在微信确认登陆以后回到url拼接有code的页面获取到code之后向后台发送登陆请求。
// 声明变量flag用来存储微信回调页面的code信息
let flag = flag.split("&")[0];
// 重定向该页面的路由(清除url中的code) - 避免发送code请求
this.$router.replace({
  path: "/login",
  query: {
    redirect: this.$route.query.redirect
  }
});

this.request({
        url: "/biz/login/wx",  // 后台接收code的接口
        method: "POST",  // 使用HTTP的POST方法传回code
        data: {
          code: flag  // 将页面存储code的flag变量以code字段传给后台
          // 此处区分登录方式的字段待定
        }
      }).then(res => {
        // 前端本地获取用户信息后的方法
      })

后端操作

接口结构

接口: (post)/biz/login/wx
参数: browser(取值为 wx,other)
返回数据(json):

// 登录成功时返回
{
    "code": 1,
    "msg": "SUCCESS",
    "data": {
        "nick": "用户昵称",
        "role_id": 2,
        "mobile": "手机号",
        "avatar": "用户头像",
        "birthday": 1578909982972,
        "gender": 2,
        "location": "地区",
        "summary": "用户简介",
        "eval": true,
        "status": "Complete",
        "last_login": 1578909982972,
        "id": "id",
        "create_time": 1571755690000,
        "update_time": 1578885503000
    }
}

// 登录失败时返回
{
    "code": 0,
    "msg": "FAILURE"
}
1 获取access_token

收到登录请求后首先通过code向微信服务器换取access_token。
根据不同的浏览器类型使用相应的appid和secret

// 请求url(Get)
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 是否必须 说明
appid 应用唯一标识
secret 应用密钥AppSecret
code 填写第一步获取的code参数
grant_type 填authorization_code

微信浏览器登录时使用公众号appid和secret, 其他浏览器登录使用网站应用appid和secret

返回数据说明
名称 类型 说明
access_token String access_token
expires_in int access_token有效时间
refresh_token String refresh_token
openid String open_id
scope String 授权作用域

当获取数据出错时,返回结果中包含"errCode"字段, 登录失败

2 拉取用户信息

通过第一步中获取到的access_token和openid拉取user_info

// 请求url(Get)
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
参数说明
参数 是否必须 说明
access_token 上一步中获取到的access_token
openid 微信用户唯一标识,上一步中获取到的openid
返回数据说明
名称 类型 说明
openid String open_id
unionid String union_id
nickname String 用户昵称
sex int 性别
province String
city String 城市
country String 国家
headimgurl String 用户头像
privilege Array 用户权限

当获取数据出错时,返回结果中包含"errCode"字段, 登录失败

3 生成或获取本地用户
  • 通过union_id获取第三方平台账号
  • 第三方平台账号存在时通过uid获取用户数据,否则继续
  • 使用微信登录的账户需要将其用户数据转换成本地用户并存储
  • 添加用户缓存
  • 创建或更新用户Auth数据
  • 更新ES(UserIndex)
  • 创建用户媒体
4 返回用户数据

将用户数据返回到前台

时序图

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 223,726评论 6 521
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,697评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 170,734评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,508评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,522评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,051评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,429评论 3 427
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,403评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,930评论 1 323
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,977评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,122评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,763评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,454评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,931评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,047评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,613评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,150评论 2 363

推荐阅读更多精彩内容