Vue implements third-party login——qq

Table of contents

1. Introduction

How to apply for QQ login

 Solve the problem of opening a new window after clicking login

 Two, used in the vue project

(1) Introduction and use

(2) Automatically generated code conversion a link jump  

(3) Map the test address to the local

3. Three routes after landing

first route

second route

third route


1. Introduction

overall process

  • On the login page, at the QQ login picture, give it the function of opening the QQ login page.

  • The redirected page gets the unique identifier openId given by QQ, and checks whether the account has been bound in the background according to the openId.

    • If bound, complete the login.

    • not bound

      • If you have an account, bind your mobile phone number to log in.

      • If you do not have an account, complete the account information to log in.

  • After successful login, jump to the home page, or the source page.

How to apply for QQ login

Reference documents:

  1. You must have a website that has been filed and has a login function. The website needs to have the logic of QQ login (login page, jump back page).

  2. Perform identity authentication on QQ Internet and pass the review.

  3. Create an application on QQ Internet, fill in the domain name of your own website, record number, and callback address. Moderated.

  4. After passing the review, it will give: application ID, application key callback address.

The above four steps are generally completed by the backend or operation and maintenance to complete the QQ login

test

Here are the appid and uri used for testing (passed the official QQ certification)

# appid			  :10055xxxx
# redirect_uri :http://www.corho.com:8080/#/login/callback

After successfully applying for the QQ login function, we can use the SDK tool provided by qq to complete the login related functions.  

 common project use

<script src="http://connect.qq.com/qc_jssdk.js" data-appid="xxxx" data-redirecturi="http://www.corho.com:8080/#/login/callback"></script>

<span id="qqLoginBtn"></span>

<script>
    QC.Login({
         btnId: 'qqLoginBtn'
    })
</script>

Through QC.Login, a qq login icon can be automatically generated on the page,  and you can jump after clicking it, but you can’t jump to the specified page even if you see the effect

 Solve the problem of opening a new window after clicking login

 The generated code is an a tag wrapped with an img. We only need to take the link as a whole and delete window.open and so on. Only the herf jump of the a link

<a href="https://graph.qq.com/oauth2.0/authorize?client_id=xxx;response_type=token&amp;scope=all&amp;redirect_uri=http%3A%2F%2Fwww.corho.com%3A8080%2F%23%2Flogin%2Fcallback">
    <img src="https://qzonestyle.gtimg.cn/qzone/vas/opensns/res/img/Connect_logo_7.png" alt="QQ登录" border="0">
</a>

 Two, used in the vue project

(1) Introduction and use

Because multiple components may need to use qq to log in, it is cumbersome to directly import each component, so directly importing it in piublic/index.html is equivalent to npm i qc

The data-appid and redirecturi filled in are the test account and password for this project application

<script src="http://connect.qq.com/qc_jssdk.js" data-appid="xxx" data-redirecturi="http://www.corho.com:8080/#/login/callback"></script>

used in the component

import QC from 'qc' 
<span id="qqLoginBtn"></span>
onMounted(() => {
   // 组件渲染完毕,使用QC生成QQ登录按钮
   QC.Login({
     btnId: 'qqLoginBtn'
   })
 })

 If you don’t do this step qc is to find node_modules but there is no npm i will report an error

  //  这个是设置外部扩展,模块为qc变量名为QC,导入qc将不做打包。
  configureWebpack: {
    externals: {
      qc: 'QC'
    }
  },

Tell wepback that QC is an external extension:

  1. If you encounter import 'qc', don't look for it under node_modules.

  2. When npm run build, do not package qc.

(2) Automatically generated code conversion a link jump  

After getting the a link in the debugging tool, delete all the above. The premise is that there is an id after application.

     <a href="https://graph.qq.com/oauth2.0/authorize?client_id=xxxxx&amp;response_type=token&amp;scope=all&amp;redirect_uri=http%3A%2F%2Fwww.corho.com%3A8080%2F%23%2Flogin%2Fcallback"><img src="https://qzonestyle.gtimg.cn/qzone/vas/opensns/res/img/Connect_logo_7.png" alt="QQ登录" border="0"></a>

(3) Map the test address to the local

The callback page after login is http://www.corho.com:8080/#/login/callback This address does not start with localhost, it is not our local address

modify host

Since the domain name is www.corho.com and localhost are inconsistent, the page cannot be called back, and the hosts address needs to be modified locally.

 windows

1. 找到 C:\Windows\System32\drivers\etc 下hosts文件
2. 在文件末尾中加入一行  127.0.0.1       www.corho.com
3. 保存即可。
# 如果提示没有权限
1. 将hosts文件移到桌面,然后进行修改,确认保存。
2. 将桌面hosts文件替换c盘文件

 mac OS

1. 打开命令行窗口
2. 输入:sudo vim /etc/hosts
3. 按下:i 键
4. 输入:127.0.0.1       www.corho.com
5. 按下:esc
6. 按下:shift + :
7. 输入:wq 回车即可

Need to enable webpack server permissions

IP or domain name access

in vue.config.js

// 这个是给webpack-dev-server开启可IP和域名访问权限。
chainWebpack: config => {
  config.devServer.disableHostCheck(true)
}

After restarting, if you try to log in again at this time, you will be transferred to the local address, but the local address does not have a route set, so an empty page is displayed

configure routing

 { path: '/login/callback', component: () => import('@/views/login/callback.vue') }

Then you can go to the specified routing component to do the operation

3. Three routes after landing

  • Registered and bound ---> login successfully, jump to the home page, or the source page

  • Registered, unbound, bound mobile phone number ----> successful login, jump to the home page, or the source page

  • Not registered, complete account information -----> login successfully, jump to the home page, or the source page

background knowledge

Check if you are logged in

QC.Login.check() :返回true|false, 用来检查是否登录

Get login credential Id

QC.Login.getMe(unionId=>{console.log(unionId)})

Get qq information (avatar nickname)

QC.api('get_user_info').success(res=>console.log(res))

  1. Obtain unionId through QQ API (QC.Login.getMe)

  2. Call the interface of this project to log in according to the unionId . If successful, it means that it has been registered and bound:

  3. Record the returned user information

  4. Jump page.

first route

Use the id returned by qq to call the local interface

Success: The returned information is user information, call the actions in vuex to save the information and jump to the homepage after saving

Failure: stay put in the catch and wait for the other two routes

<script>
import LoginHeader from './components/loginHeader.vue'
import LoginFooter from './components/loginFooter.vue'
import { ref } from 'vue'
import { userQQLogin } from '@/api/user'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
import Message from '@/components/XtxMessage.vue'
import QC from 'qc'
import CallbackBind from './components/callbackBind.vue'
import CallbackPatch from './components/callbackPatch.vue'
export default {
  name: 'PageCallback',
  components: { LoginHeader, LoginFooter, CallbackBind, CallbackPatch },
  setup () {
    const unionId = ref(null)
    const store = useStore()
    const router = useRouter()
    QC.Login.check() && QC.Login.getMe(openId => {
      console.log(openId)
      unionId.value = openId
      userQQLogin(openId).then(data => {
        //   走到then说明成功
        // 1. 存储用户信息
        store.commit('user/setUser', data.result)
        // 跳转到主页
        router.push('/')
        // 弹框提示
        console.log(data)
        Message({ type: 'success', text: '登陆成功!' })
      }).catch(() => {
        //   走到catch说明失败 就留在此页面
        console.log('没有绑定 留此页面')
      })
    })
    const hasAccount = ref(true)
    return { hasAccount, unionId }
  }
}
</script>

second route

If you already have an account, please bind your mobile phone: it means that you already have an account for the current project and directly bind your mobile phone number

route:

Obtaining the verification code: 1. Determine whether the verification of the mobile phone number is correct 2. Call the interface for obtaining the verification code   

Call the binding interface: 1. Check whether the user name and verification code form verification is correct 2. Call the interface 3. Prompt text 4. Jump to the home page

<script>
import { ref, reactive } from 'vue'
import QC from 'qc'
import { Form, Field } from 'vee-validate'
import { mobile, code } from '@/utils/validate'
import { useCountDown } from '@/compositions/index'
import { userQQBindCode } from '@/api/user'
import Message from '@/components/message'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'

export default {
  name: 'CallbackBind',
  components: {
    Form, Field
  },
  props: {
    unionId: {
      type: String,
      default: ''
    }
  },
  setup (props) {
    // 1. 定义数据项:qq头像 昵称
    const nickname = ref('')
    const avatar = ref('')
    QC.Login.check() && QC.api('get_user_info').success(res => {
      avatar.value = res.data.figureurl_2
      nickname.value = res.data.nickname
    }) // 获取当前登录的QQ账号的信息

    const target = ref(null)
    // 表单数据对象
    const formData = reactive({
      mobile: '13241051259',
      code: ''
    })
    // 校验规则
    const mySchema = {
      mobile: mobile,
      code: code
    }
    const store = useStore()
    const router = useRouter()
    const { start, time } = useCountDown()
    // 发送验证码倒计时
    const send = async () => {
      // 如果手机号格式不正确
      if (mobile(formData.mobile) !== true) {
        Message({ type: 'error', text: '手机号格式错误' })
        return
      }
      if (time >= 0) return
      try {
        await userQQBindCode(formData.mobile).then((res) => {
          Message({ type: 'success', text: '获取验证码成功!' })
          start(60)
        })
      } catch (error) {
        Message({ type: 'warn', text: error.response.data.message + ', 请稍后重试' || '获取验证码失败!' })
      }
    }

    // 开始绑定
    const binding = () => {
      console.log(props.unionId)
      target.value.validate().then((vilid) => {
        // 开始绑定
        if (vilid) doBingding()
      }
      ).catch(vlida => console.log(vlida))
    }
    const doBingding = async () => {
      try {
        await store.dispatch('user/userQQBindLogin', { unionId: props.unionId, mobile: formData.mobile, code: formData.code })
        Message({ type: 'success', text: '提交成功!' })
        router.push('/')
      } catch (error) {
        console.dir(error)
        Message({ type: 'error', text: error.message || '提交失败' })
      }
    }
    return { nickname, avatar, formData, target, mySchema, send, time, binding }
  }
}
</script>

third route

 No project account, no mobile phone number bound

route:

First check the user name and call the interface to see if the current user name exists  

Verify that the two passwords are equal

Obtaining the verification code: 1. Determine whether the verification of the mobile phone number is correct 2. Call the interface for obtaining the verification code   

Call the binding interface: 1. Whether all form validations are correct 2. Call the interface 3. Prompt text 4. Jump to the home page

<script>
import { reactive, ref } from 'vue'
import { Form, Field } from 'vee-validate'
import { mobile, code, rePassword, password, accountApi as account } from '@/utils/validate'
import { useCountDown } from '@/compositions/index'
import Message from '@/components/message'
import { userQQPatchCode } from '@/api/user'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
export default {
  name: 'CallbackPatch',
  components: {
    Form, Field
  },
  props: {
    unionId: {
      type: String,
      default: ''
    }
  },
  setup (props) {
    // 1. 表单校验 多两个校验:用户名是否存在,再次输入密码是否一致
    // 2. 发送短信验证码:接口API定义
    // 3. 完善信息

    // 表单数据对象
    const formData = reactive({
      account: null,
      mobile: null,
      code: null,
      password: null,
      rePassword: null
    })
    // 校验表单
    const mySchema = {
      account,
      mobile,
      code,
      password,
      rePassword
    }

    const { start, time } = useCountDown()
    // 发送验证码倒计时
    const send = async () => {
      // 如果手机号格式不正确
      if (mobile(formData.mobile) !== true) {
        Message({ type: 'error', text: '手机号格式错误' })
        return
      }
      if (time >= 0) return
      try {
        await userQQPatchCode(formData.mobile).then((res) => {
          Message({ type: 'success', text: '获取验证码成功!' })
          start(60)
        })
      } catch (error) {
        Message({ type: 'warn', text: error.response.data.message + ', 请稍后重试' || '获取验证码失败!' })
      }
    }

    // 开始绑定
    const target = ref(null)
    const store = useStore()
    const router = useRouter()

    // 立即提交
    const submit = () => {
      console.log(props.openId)
      target.value.validate().then((vilid) => {
        // 开始绑定
        if (vilid) doSubmit()
      }
      ).catch(vlida => console.log(vlida))
    }
    const doSubmit = async () => {
      try {
        await store.dispatch('user/userQQPatchLogin', {
          unionId: props.unionId,
          mobile: formData.mobile,
          code: formData.code,
          account: formData.account,
          password: formData.password
        })
        Message({ type: 'success', text: '提交成功!' })
        router.push('/')
      } catch (error) {
        console.dir(error)
        Message({ type: 'error', text: error.message || '提交失败' })
      }
    }
    return { formData, mySchema, send, time, submit, target }
  }
}
</script>

Guess you like

Origin blog.csdn.net/m0_46846526/article/details/119243300#comments_26392827