前端第三方登录-QQ/微信登录

第三方登录前置条件

想要能通过第三方平台登录,先要经过第三方平台的同意,也就是在第三方平台进行对应的注册和认证。

针对QQ,我们需要QQ互联平台去注册和认证,注册和认证流程他们网站详细说明,在此不介绍。

页面交互上第三方登录流程

QQ登录为例

  1. 点击登录按钮,
  2. 弹出一个窗口,展示二维码
  3. 手机打开APP扫码,手机跳转到同意页面,点击同意;然后浏览器端的显示登录成功
  4. 手机显示登录成功后,会有两种情况
    1. 当前用户已经注册 => 直接登录
    2. 当前用户没有注册 => 执行注册流程,注册成功即可登录

前端代码上第三方登录做了哪些事情

QQ登录为例

  1. 点击第三方登录按钮,执行window.open方法,打开一个指定url窗口,该url指向第三方登录页面,里面会显示登录的二维码。
  2. 手机app扫码并且同意登录后,该第三方页面会跳转到登录成功页面,之所以知道登录成功,是因为该页面会一直轮询查询是否登录成功。
  3. 登录成功之后,该页面会进行跳转,跳转的url为我们预先指定的url,该页面能拿到第三方的用户信息,如昵称头像等,该信息为登录需要用到的信息。
  4. 到此,在第三方页面交互事情已经全部做完,剩余都是本平台内的事情。
    1. 判断该第三方用户是否在本平台已经注册(由后台判断),我们不能从第三方手中拿到用户关键信息(如手机号,密码等),只能拿到非关键信息如头像昵称,我们仅能通过拿到的第三方信息去判断有没有注册。
    2. 如果已经注册过,则直接登录
    3. 如果没有注册,执行注册功能(执行注册通常是让用户输入一个唯一标识如手机号,然后把这个唯一标识和第三方信息关联起来)

总结要做两件事

一:对接第三方平台获取第三方用户信息

二:利用该用户信息,完成注册

QQ登录对接流程(PC端)

总体流程分为以下几五步

  1. 展示 QQ 登录二维码
  2. 获取用户信息
  3. 完成跨页面数据传输
  4. 判断用户是否已注册
  5. 完成 QQ 对接

一:展示QQ二维码

首先我们需要在index.html中引入sdk,其中的appidredirecturi是我们在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登录整体流程是相似的,但在具体代码实现上会有差别。

首先我们仍然要先去微信平台做注册,微信一共分为微信公众平台和微信开放平台。

微信公众平台

地址:mp.weixin.qq.com/

作用:用于管理、开放微信公众号(包括订阅号、服务号、企业号),相当于微信公众号的后台运营、管理系统。

微信开放平台

地址:open.weixin.qq.com/

作用:主要面对移动应用、网站应用开发者,为其提供微信登录、分享、支付等相关权限和服务.

注册过程不在此介绍。

微信登录总体实现步骤

  1. 通过 微信登录前置数据获取 接口,获取登录数据(比如 APP ID
  2. 根据获取到的数据,拼接得到 open url 地址
  3. 打开该地址,展示微信登录二维码
  4. 移动端微信扫码确定登录
  5. 从当前窗口中解析 window.location.search 得到用户的 code 数据
  6. 根据 appId、appSecret、code 通过接口获取用户的 access_token
  7. 根据 access_token 获取用户信息
  8. 通过用户信息触发 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/微信登录怎么做的,回答

待完成...

草稿

  1. 先注册...讲解..
  2. 交互讲解描述...
  3. 根据交互,讲核心代码的实现,点出关键步骤,不讲没用的细节。
  4. 总结微信和qq的异同,同样指点出关键步骤。
相关推荐
长天一色4 分钟前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_23422 分钟前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河24 分钟前
CSS总结
前端·css
BigYe程普1 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
余生H1 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍1 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
axihaihai1 小时前
网站开发的发展(后端路由/前后端分离/前端路由)
前端
流烟默1 小时前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch
2401_857297912 小时前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
茶卡盐佑星_2 小时前
meta标签作用/SEO优化
前端·javascript·html