你的网站如何接入QQ,微信登录
主要实现步骤
- 对接第三方平台,获取第三方平台的用户信息。
- 利用该用户信息,完成本应用的注册。
qq登录接入
接入前的配置
登录后,点击头像,进行开发者信息填写,等待审核。
邮箱验证后,等待审核。
审核通过后,然后就可以创建应用了。
然后填写一些网站信息,等待审核。审核通过后,即可使用。
开始接入
- 导入qq登录的sdk
<script type="text/javascript" charset="utf-8" src="https://connect.qq.com/qc_jssdk.js" data-appid="您应用的appid"
data-redirecturi="qq扫码后的回调地址(上面配置中可以查到)">script>
- 点击qq登录,弹出扫码窗口。
// QQ 登录的 URL
const QQ_LOGIN_URL =
'https://graph.qq.com/oauth2.0/authorize?client_id=您的appid&response_type=token&scope=all&redirect_uri=您的扫码后的回调地址'
window.open(
QQ_LOGIN_URL,
'oauth2Login_10609',
'height=525,width=585, toolbar=no, menubar=no, scrollbars=no, status=no, location=yes, resizable=yes'
)
- 挂起qq登录。需要注意的是,扫码登录成功后,调试代码需要在线上环境。
"qqLoginBtn" v-show="false">
// QQ 登录挂起
onMounted(() => {
QC.Login(
{
btnId: 'qqLoginBtn' //插入按钮的节点id
},
// 登录成功之后的回调,但是需要注意,这个回调只会在《登录回调页面中被执行》
// 登录存在缓存,登录成功一次之后,下次进入会自动重新登录(即:触发该方法,所以我们应该在离开登录页面时,注销登录)
// data就是当前qq的详细信息
(data, opts) => {
console.log('QQ登录成功')
// 1. 注销登录,否则在后续登录中会直接触发该回调
QC.Login.signOut()
// 2. 获取当前用户唯一标识,作为判断用户是否已注册的依据。(来决定是否跳转到注册页面)
const accessToken = /access_token=((.*))&expires_in/.exec(
window.location.hash
)[1]
// 3. 拼接请求对象
const oauthObj = {
nickname: data.nickname,
figureurl_qq_2: data.figureurl_qq_2,
accessToken
}
// 4. 完成跨页面传输 (需要将数据传递到项目页面,而非qq登录弹框页面中进行操作)
brodacast.send(oauthObj)
// 针对于 移动端而言:通过移动端触发 QQ 登录会展示三个页面,原页面、QQ 吊起页面、回调页面。并且移动端一个页面展示整屏内容,且无法直接通过 window.close() 关闭,所以在移动端中,我们需要在当前页面继续进行后续操作。
oauthLogin(LOGIN_TYPE_QQ, oauthObj)
// 5. 在 PC 端下,关闭第三方窗口
window.close()
}
)
})
- 跨页面窗口通信
想要实现跨页面信息传输,通常有两种方式:
- BroadcastChannel:允许 同源 的不同浏览器窗口,Tab页,frame或者 iframe 下的不同文档之间相互通信。但是会存在兼容性问题。
- localStorage + window.onstorage:通过localStorage 进行 同源 的数据传输。用来处理 BroadcastChannel 不兼容的浏览器。以前写过一篇文章
// brodacast.js
// 频道名
const LOGIN_SUCCESS_CHANNEL = 'LOGIN_SUCCESS_CHANNEL'
// safari@15.3 不支持 BroadcastChannel,所以我们需要对其进行判定使用,在不支持 BroadcastChannel 的浏览器中,使用 localstorage
let broadcastChannel = null
if (window.BroadcastChannel) {
broadcastChannel = new BroadcastChannel(LOGIN_SUCCESS_CHANNEL)
}
/**
* 等待 QQ 登录成功
* 因为 QQ 登录会在一个新的窗口中进行,用户扫码登录成功之后会回调《新窗口的 QC.Login 第二参数 cb》,而不会回调到原页面。
* 所以我们需要在《新窗口中通知到原页面》,所以就需要涉及到 JS 的跨页面通讯,而跨页面通讯指的主要就是《同源页面的通讯》
* 同源页面的通讯方式有很多,我们这里主要介绍:
* 1. BroadcastChannel ->
* 2. window.onstorage:注意:该事件不在导致数据变化的当前页面触发
*/
/**
* 等待回调,它将返回一个 promise,并携带对应的数据
*/
const wait = () => {
return new Promise((resolve, reject) => {
if (broadcastChannel) {
// 触发 message 事件时的回调函数
broadcastChannel.onmessage = async (event) => {
// 改变 promise 状态
resolve(event.data)
}
} else {
// 触发 localStorage 的 setItem 事件时回调函数
window.onstorage = (e) => {
// 判断当前的事件名
if (e.key === LOGIN_SUCCESS_CHANNEL) {
// 改变 promise 状态
resolve(JSON.parse(e.newValue))
}
}
}
})
}
/**
* 发送消息。
* broadcastChannel:触发 message
* localStorage:触发 setItem
*/
const send = (data) => {
if (broadcastChannel) {
broadcastChannel.postMessage(data)
} else {
localStorage.setItem(LOGIN_SUCCESS_CHANNEL, JSON.stringify(data))
}
}
/**
* 清除
*/
const clear = () => {
if (broadcastChannel) {
broadcastChannel.close()
broadcastChannel = null
}
localStorage.removeItem(LOGIN_SUCCESS_CHANNEL)
}
export default {
wait,
send,
clear
}
- 拿到数据后,进行登录(自己服务器登录接口)操作。
- 传入对应参数(loginType, accessToken)等参数进行用户注册判断。
- 通过accessToken判断用户已经注册,那么我们就直接在后台查出用户名和密码直接登录了。
- 通过accessToken判断用户未注册,那么我们将跳转到注册页面,让其注册。
// 打开视窗之后开始等待
brodacast.wait().then(async (oauthObj) => {
// 登录成功,关闭通知
brodacast.clear()
// TODO: 执行登录操作
oauthLogin("QQ", oauthObj)
})
// oauthLogin.js
import store from '@/store'
import router from '@/router'
import { message } from '@/libs'
import { LOGIN_TYPE_OAUTH_NO_REGISTER_CODE } from '@/constants'
/**
* 第三方登录统一处理方法
* @param {*} oauthType 登录方式
* @param {*} oauthData 第三方数据
*/
export const oauthLogin = async (oauthType, oauthData) => {
const code = await store.dispatch('user/login', {
loginType: oauthType,
...oauthData
})
// 返回 204 表示当前用户未注册,此时给用户一个提示,走注册页面
if (code === LOGIN_TYPE_OAUTH_NO_REGISTER_CODE) {
message('success', `欢迎您 ${oauthData.nickname},请创建您的账号`, 6000)
// 进入注册页面,同时携带当前的第三方数据和注册标记
router.push({
path: '/register',
query: {
reqType: oauthType,
...oauthData
}
})
return
}
// 否则表示用户已注册,直接进入首页
router.push('/')
}
微信扫码登录接入
登录后,进行对应的应用注册,填写一大堆详细信息,然后进行交钱,就可以使用微信登录了。
开始接入
整个微信登录流程与QQ登录流程略有不同,分为以下几步:
1.通过 微信登录前置数据获取 接口,获取登录数据(比如 APP ID)。就是后台将一些敏感数据通过接口返回。
2.根据获取到的数据,拼接得到 open url 地址。打开该地址,展示微信登录二维码。移动端微信扫码确定登录。
// 2. 根据获取到的数据,拼接得到 `open url` 地址
window.open(
`https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`,
'',
'height=525,width=585, toolbar=no, menubar=no, scrollbars=no, status=no, location=yes, resizable=yes'
)
3.等待用户扫码后,从当前窗口中解析 window.location.search
得到用户的 code
数据。 微信扫码后,会重定向到登录页面。
/**
* 微信登录成功之后的窗口数据解析
*/
if (window.location.search) {
const code = /code=((.*))&state/.exec(window.location.search)[1]
if (code) {
brodacast.send({
code
})
// 关闭回调网页
window.close()
}
}
4.根据 appId、appSecret、code 通过接口获取用户的 access_token
5.根据 access_token 获取用户信息
6.通过用户信息触发 oauthLogin 方法。
调用的接口,都是后端通过微信提供的api来获取到对应的数据,然后再通过接口返回给开发者。 以前也写过微信登录文章
// 等待扫码登录成功通知
brodacast.wait().then(async ({ code }) => {
console.log('微信扫码登录成功')
console.log(code)
// 微信登录成功,关闭通知
brodacast.clear()
// 获取 AccessToken 和 openid
const { access_token, openid } = await getWXLoginToken(
appId,
appSecret,
code
)
// 获取登录用户信息
const { nickname, headimgurl } = await getWXLoginUserInfo(
access_token,
openid
)
console.log(nickname, headimgurl)
// 执行登录操作
oauthLogin(LOGIN_TYPE_WX, {
openid,
nickname,
headimgurl
})
})
需要注意的是,在手机端,普通h5页面是不能使用微信扫码登录的。
总结
相同点
- 接入前需要配置一些内容信息。
- 都需要在线上环境进行调试。
- 都是扫码后在三方窗口中获取对应的信息,发送到当前项目页面进行请求,判断用户是否已经注册,还是未注册。已经注册时,调用login接口时,password直接传递空字符串即可,后端可以通过唯一标识,获取到对应的用户名和密码,直接返回token进行登录。未注册,就跳转到注册页面,让其注册。
不同点
- qq接入需要导入qc_sdk。
- qq直接扫码后即可获取到用户信息,就可以直接调用login接口进行判断用户是否注册了。
- 微信扫码后,获取
code
来换取access_token, openid
,然后再通过access_token, openid
来换取用户信息。然后再调用login接口进行判断用户是否注册了。
作者:Spirited_Away
来源:juejin.cn/post/7311343161363234866
来源:juejin.cn/post/7311343161363234866