Table of contents
Solve the problem of opening a new window after clicking login
(2) Automatically generated code conversion a link jump
(3) Map the test address to the local
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:
-
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).
-
Perform identity authentication on QQ Internet and pass the review.
-
Create an application on QQ Internet, fill in the domain name of your own website, record number, and callback address. Moderated.
-
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&scope=all&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:
-
If you encounter import 'qc', don't look for it under node_modules.
-
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&response_type=token&scope=all&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))
-
Obtain unionId through QQ API (QC.Login.getMe)
-
Call the interface of this project to log in according to the unionId . If successful, it means that it has been registered and bound:
-
Record the returned user information
-
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>