vue实现第三方登录 |
您所在的位置:网站首页 › qq邮箱微信登录 › vue实现第三方登录 |
目录 一、介绍 如何申请QQ登录 解决点击登录后打开一个新窗口 二、vue项目中使用 (1)引入使用 (2)自动生成的代码转换a链接跳转 (3)将测试地址映射到本地 三、登陆后的三条路线 第一条路线 第二条路线 第三条路线 一、介绍整体流程 在登录页面,QQ登录图片处,赋予其打开QQ登录页面功能。 回跳的页面得到QQ给的唯一标识openId,根据openId去后台查询是否已经绑定过账户。 如果绑定过,完成登录。 没有绑定过 有账号的,绑定手机号,即为登录。 没账号的,完善账户信息,即为登录。 登录成功后,跳转首页,或者来源页面。 如何申请QQ登录参考文档: 准备工作 QQ互联JS_SDK 自己要有一个已备案的,本身具有登录功能的网站。网站需要有QQ登录的逻辑(登录页面,回跳页面)。 在QQ互联上进行身份认证,审核通过。 在QQ互联上创建应用,填入自己网站的域名,备案号,回调地址。等待审核。 审核通过后,会给出:应用ID,应用key 回调地址。 以上四个步骤,一般由后端或运维完成,才能完成QQ登录 测试 这里已有测试使用的appid和uri (是通过了QQ官方认证) # appid :10055xxxx # redirect_uri :http://www.corho.com:8080/#/login/callback在申请QQ登录功能成功之后,我们就可以使用qq提供的SDK工具来完成登录相关功能。 普通项目使用 QC.Login({ btnId: 'qqLoginBtn' })通过 QC.Login 就可以自动在页面上生成一个qq登录图标 通过生成的代码是一个a标签包着一个img 我们只需要把链接整体拿过来 把window.open 之类的删掉 只有a链接的herf跳转 ![]() 因为多个组件可能都要使用qq登录 如果直接引在每个组件很繁琐 所以直接引入在piublic/index.html中 等价于 npm i qc 填写的data-appid和redirecturi是本项目申请的测试账号和密码 在组件中使用 import QC from 'qc' onMounted(() => { // 组件渲染完毕,使用QC生成QQ登录按钮 QC.Login({ btnId: 'qqLoginBtn' }) })如果不做此步qc 是去找node_modules去找但是 并没有npm i 会报错 // 这个是设置外部扩展,模块为qc变量名为QC,导入qc将不做打包。 configureWebpack: { externals: { qc: 'QC' } },告诉wepback,QC 是外部拓展: 如果遇到 import 'qc' 不要去node_modules下找了。 npm run build时,也不要去打包 qc。 (2)自动生成的代码转换a链接跳转拿到调试工具中的a链接后把上面写的全删了 前提是有申请后的 id ![]() 登录之后的回调页面是http://www.corho.com:8080/#/login/callback 这个地址不是localhost打头的 ,并不是我们的本地地址 修改host 由于域名是www.corho.com和localhost不一致无法回调页面,需要在本地修改hosts地址。 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 回车即可需要开启webpack服务器权限 IP或域名访问 在vue.config.js中 // 这个是给webpack-dev-server开启可IP和域名访问权限。 chainWebpack: config => { config.devServer.disableHostCheck(true) }重启后,这时候再去尝试登录后就会调到 本地地址 但是本地地址没有设置路由 所以显示的是空页面 配置路由 { path: '/login/callback', component: () => import('@/views/login/callback.vue') }接下俩就可以去 指定的路由组件中去做操作 三、登陆后的三条路线已注册,已绑定 ---> 登录成功,跳转首页,或者来源页面 已注册,未绑定,绑定手机号 ----> 登录成功,跳转首页,或者来源页面 未注册,补充完善账户信息 ----->登录成功,跳转首页,或者来源页面 背景知识 检查是否登录 QC.Login.check() :返回true|false, 用来检查是否登录获取登录凭证Id QC.Login.getMe(unionId=>{console.log(unionId)})获取qq信息(头像 昵称) QC.api('get_user_info').success(res=>console.log(res))通过QQ的API(QC.Login.getMe)获取unionId 根据unionId去调用本项目的接口进行登录,如果成功,就代表已注册已绑定: 记录返回的用户信息 跳转页面。 第一条路线拿qq返回的id调用本地接口 成功:返回的信息是用户信息,调用vuex中的actions保存信息 保存完之后跳转到主页 失败:在catch中原地不动 等待其他两条路线 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 } } } 第二条路线已有账号 请绑定手机 :意思是已有当前项目的账号了 直接绑定手机号 路线: 获取验证码 : 1. 判断手机号校验是否正确 2. 调用获取验证码接口 调用绑定接口: 1. 看用户名和验证码 表单校验是否正确 2.调用接口 3.提示文本 4.跳到主页 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 } } } 第三条路线没有项目账号,也没有绑定手机号 路线: 首先校验用户名 调用接口 看当前用户名是否存在 校验密码 两次密码是否相等 获取验证码 : 1. 判断手机号校验是否正确 2. 调用获取验证码接口 调用绑定接口: 1. 所有表单校验是否正确 2.调用接口 3.提示文本 4.跳到主页 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 } } } |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |