第三方登录前置条件
想要能通过第三方平台登录,先要经过第三方平台的同意,也就是在第三方平台进行对应的注册和认证。
针对QQ,我们需要QQ互联平台去注册和认证,注册和认证流程他们网站详细说明,在此不介绍。
页面交互上第三方登录流程
QQ登录为例
- 点击登录按钮,
- 弹出一个窗口,展示二维码
- 手机打开APP扫码,手机跳转到同意页面,点击同意;然后浏览器端的显示登录成功
- 手机显示登录成功后,会有两种情况
- 当前用户已经注册 => 直接登录
- 当前用户没有注册 => 执行注册流程,注册成功即可登录
前端代码上第三方登录做了哪些事情
QQ登录为例
- 点击第三方登录按钮,执行
window.open
方法,打开一个指定url窗口,该url指向第三方登录页面,里面会显示登录的二维码。 - 手机app扫码并且同意登录后,该第三方页面会跳转到登录成功页面,之所以知道登录成功,是因为该页面会一直轮询查询是否登录成功。
- 登录成功之后,该页面会进行跳转,跳转的url为我们预先指定的url,该页面能拿到第三方的用户信息,如昵称头像等,该信息为登录需要用到的信息。
- 到此,在第三方页面交互事情已经全部做完,剩余都是本平台内的事情。
- 判断该第三方用户是否在本平台已经注册(由后台判断),我们不能从第三方手中拿到用户关键信息(如手机号,密码等),只能拿到非关键信息如头像昵称,我们仅能通过拿到的第三方信息去判断有没有注册。
- 如果已经注册过,则直接登录
- 如果没有注册,执行注册功能(执行注册通常是让用户输入一个唯一标识如手机号,然后把这个唯一标识和第三方信息关联起来)
总结要做两件事
一:对接第三方平台获取第三方用户信息
二:利用该用户信息,完成注册
QQ登录对接流程(PC端)
总体流程分为以下几五步
- 展示
QQ
登录二维码 - 获取用户信息
- 完成跨页面数据传输
- 判断用户是否已注册
- 完成 QQ 对接
一:展示QQ二维码
首先我们需要在index.html
中引入sdk,其中的appid
和redirecturi
是我们在QQ平台注册和备案的时候生成的。
html
<!-- QQ 登录 -->
<script type="text/javascript" charset="utf-8" src="https://connect.qq.com/qc_jssdk.js" data-appid="XXXX(你的 appid)" data-redirecturi="https://
xxxx(你配置的登录成功之后的回调)"></script>
在点击登录图标时候,通过window.open
方法弹出第三方登录页面,这个登录页面的url是固定的,里面要传对应的clinet_id
和回调url
,这两个参数是在申请应用的时候配置生成的。
同时调用QQ登录挂起方法(该方法轮询查询登录成功没有)
js
/**
* 登录按钮事件
*/
const onQQLogin = () => {
openQQWindow()
}
/**
* 处理 QQ 登录视窗
*/
const openQQWindow = async () => {
window.open(
QQ_LOGIN_URL,
'oauth2Login_10609',
'height=525,width=585, toolbar=no, menubar=no, scrollbars=no, status=no, location=yes, resizable=yes'
)
}
// QQ 登录挂起
onMounted(() => {
QC.Login(
{
btnId: 'qqLoginBtn' //插入按钮的节点id
},
// 登录成功之后的回调,但是需要注意,这个回调只会在《登录回调页面中被执行》
// 登录存在缓存,登录成功一次之后,下次进入会自动重新登录(即:触发该方法,所以我们应该在离开登录页面时,注销登录)
(data, opts) => {
console.log('QQ登录成功')
console.log(data)
// 注销登录,否则在后续登录中会直接触发该回调
QC.Login.signOut()
}
)
})
二:获取用户信息
登录成功后,页面会跳转到我们提前配置好的登录页,QQ会返回给我们用户信息,后面步骤我们会通过返回的token判断该用户是否已经在本平台注册。
js
// 2. 获取当前用户唯一标识,作为判断用户是否已注册的依据
const accessToken = /access_token=((.*))&expires_in/.exec(
window.location.hash
// 3. 拼接请求对象
const oauthObj = {
nickname: data.nickname,
figureurl_qq_2: data.figureurl_qq_2,
accessToken
}
console.log(oauthObj)
三:完成跨页面数据传输
上一步我们拿到的用户信息是在window.open
打开的窗口拿到的,现在我们要把这些信息传递给父页面,这里要用到同源下 的跨页面传输技术,通常可以用BroadcastChannel对象或者是利用localStorage
的onStorage事件存储实现,这里我们不做过多介绍。
四:判断用户是否已注册
父页面拿到用户信息后,立刻触发登录操作,发送登录接口,如果后台返回没有注册过,则跳转到注册页面,如果已经注册过,则登录成功。
js
import store from '@/store'
import router from '@/router'
import { message } from '@/libs'
/**
* 第三方登录统一处理方法
* @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登录对接流程(移动端)
移动端的登录流程和PC端基本一致,最大的不同就是,移动端没有新窗口的概念,移动端一共只有一个窗口。
所以在移动端中,我们需要在当前页面中,继续进行后续操作。不需要跨页面传输。
js
QC.Login(
...
(data, opts) => {
...
// 针对于 移动端而言:通过移动端触发 QQ 登录会展示三个页面,原页面、QQ 吊起页面、回调页面。并且移动端一个页面展示整屏内容,且无法直接通过 window.close() 关闭,所以在移动端中,我们需要在当前页面继续进行后续操作。
oauthLogin(LOGIN_TYPE_QQ, oauthObj)
// 5. 在 PC 端下,关闭第三方窗口
window.close()
}
微信对接登录
微信登录和QQ登录整体流程是相似的,但在具体代码实现上会有差别。
首先我们仍然要先去微信平台做注册,微信一共分为微信公众平台和微信开放平台。
微信公众平台
作用:用于管理、开放微信公众号(包括订阅号、服务号、企业号),相当于微信公众号的后台运营、管理系统。
微信开放平台
作用:主要面对移动应用、网站应用开发者,为其提供微信登录、分享、支付等相关权限和服务.
注册过程不在此介绍。
微信登录总体实现步骤
- 通过 微信登录前置数据获取 接口,获取登录数据(比如
APP ID
) - 根据获取到的数据,拼接得到
open url
地址 - 打开该地址,展示微信登录二维码
- 移动端微信扫码确定登录
- 从当前窗口中解析
window.location.search
得到用户的code
数据 - 根据
appId、appSecret、code
通过接口获取用户的access_token
- 根据
access_token
获取用户信息 - 通过用户信息触发
oauthLogin
方法
核心代码实现
触发微信登录,先从后台获取登录前置数据,然后通过window.open打开二维码页面地址,这个页面是的url同样是定死的,传参是从前置数据接口拿到的。
js
/**
* 触发微信登录
*/
const onWeiXinLogin = async () => {
// 1. 通过微信登录前置数据获取接口,获取登录数据
const { appId, appSecret, redirectUri, scope, state } = await getWXLoginData()
// 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'
)
// 等待扫码登录成功通知
brodacast.wait().then(async ({ code }) => {
console.log('微信扫码登录成功')
console.log(code)
})
}
微信登录成功之后,会 跳转到指定的 redirectUri 地址,并且把 code 放入到 location.search 中,所以我们可以在这里解析 search:
js
/**
* 微信登录成功之后的窗口数据解析
*/
if (window.location.search) {
const code = /code=((.*))&state/.exec(window.location.search)[1]
if (code) {
brodacast.send({
code
})
// 关闭回调网页
window.close()
}
}
到此,和微信的交互已经做完,剩下的都是自己网站内的交互。
根据微信返回的信息,获取access_token
,然后根据access_token
,获取用户信息
js
// 等待扫码登录成功通知
brodacast.wait().then(async ({ code }) => {
...
// 微信登录成功,关闭通知
brodacast.clear()
// 获取 AccessToken 和 openid
const { access_token, openid } = await getWXLoginToken(
appId,
appSecret,
code
)
console.log('access_token, openid')
console.log(access_token, openid)
})
// 等待扫码登录成功通知
brodacast.wait().then(async ({ code }) => {
...
// 获取登录用户信息
const { nickname, headimgurl } = await getWXLoginUserInfo(access_token, openid)
console.log(nickname, headimgurl)
})
拿到用户信息以后,发送登录接口
js
// 等待扫码登录成功通知
brodacast.wait().then(async ({ code }) => {
...
// 执行登录操作
oauthLogin(LOGIN_TYPE_WX, {
openid,
nickname,
headimgurl
})
})
面试问第三方QQ/微信登录怎么做的,回答
待完成...
草稿
- 先注册...讲解..
- 交互讲解描述...
- 根据交互,讲核心代码的实现,点出关键步骤,不讲没用的细节。
- 总结微信和qq的异同,同样指点出关键步骤。