小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
前言
微信扫码登录是非常常见的需求,让微信用户使用微信登录第三方应用或网站,无非两种展现方式
- 第一种,重定向到微信指定的扫码页面
- 第二种,网站将微信登录二维码内嵌到页面中 该模式整体流程:
- 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
- 通过code参数加上AppID和AppSecret等,通过API换取access_token;
- 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。 参数说明
参数 | 是否必须 | 说明 |
---|---|---|
self_redirect | 否 | true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false:手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false。 |
id | 是 | 第三方页面显示二维码的容器id |
appid | 是 | 应用唯一标识,在微信开放平台提交应用审核通过后获得 |
scope | 是 | 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可 |
redirect_uri | 是 | 重定向地址,需要进行UrlEncode |
state | 否 | 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 |
style | 否 | 提供"black"、"white"可选,默认为黑色文字描述。详见文档底部FAQ |
href | 否 | 自定义样式链接,第三方可根据实际需求覆盖默认样式。详见文档底部FAQ |
这里主要说的是第二种,将微信二维码内嵌到网站页面中,在网站内就能完成登录,无需跳转到微信域下登录后再返回,提升微信登录的流畅性与成功率。
这里使用vue-wxlogin,方便组件化模块化引入
npm install vue-wxlogin --save-dev
封装成组件
<template>
<div class="wxLogin">
<span class="title">微信扫一扫登录</span>
<div class="main_wx">
<wxlogin
v-if="appid && redirect_uri"
:appid="appid"
scope="snsapi_login"
:redirect_uri="redirect_uri"
:href="href"
:state="state"
></wxlogin>
</div>
<p>
请使用微信扫描二维码登录
</p>
</div>
</template>
<script>
import wxlogin from 'vue-wxlogin'
import api from '@api/index'
export default {
name: 'wxLogin',
components: { wxlogin },
data () {
return {
appid: '',
redirect_uri: '',
state: '1',
href: '' // 自定义样式链接
}
},
mounted () {
this.getWeChatUrl()
},
methods: {
// 获取微信appid和回调地址redirect_uri,指定内嵌的路由地址weChatLogin
getWeChatUrl () {
api.wachatQrUrl().then(res => {
if (res && res.code === '0000') {
const data = res.data
this.appid = data.appId
this.redirect_uri = data.wxCallbackUrl + 'weChatLogin'
}
})
}
}
}
</script>
在导航守卫router.beforeEach函数中进行拦截判断,获取url中的code,根据code调用接口进行登录验证
router.beforeEach((to, from, next) => {
let code = null
if (to.name === 'weChatLogin') {
code = to.query.code || null
}
// 微信授权登陆
if (code) {
api.weChatOauth(code).then(res => {
if (res?.code === '0000') {
// 登录成功,并提示,跳转到用户主页面
Message({
type: 'success',
message: '登录成功'
})
router.push({ path: '/index' })
}
})
} else {
next()
}
})