目次
1. はじめに
全体的なプロセス
-
ログイン ページの QQ ログイン画面に、QQ ログイン ページを開く機能を与えます。
-
リダイレクトされたページは、QQ によって指定された一意の識別子 openId を取得し、openId に従ってアカウントがバックグラウンドでバインドされているかどうかを確認します。
-
バインドされている場合は、ログインを完了します。
-
バインドされていません
-
アカウントをお持ちの場合は、携帯電話番号をバインドしてログインします。
-
アカウントをお持ちでない場合は、アカウント情報を入力してログインしてください。
-
-
-
ログインに成功したら、ホームページまたはソース ページにジャンプします。
QQログインの申請方法
参照文書:
-
申請済みでログイン機能のある Web サイトが必要です。Web サイトには QQ ログインのロジック (ログイン ページ、ジャンプバック ページ) が必要です。
-
QQインターネット上で本人認証を行い、審査に合格します。
-
QQ Internet でアプリケーションを作成し、自分の Web サイトのドメイン名、レコード番号、コールバック アドレスを入力します。モデレート。
-
レビューに合格すると、アプリケーション ID、アプリケーション キーのコールバック アドレスが提供されます。
上記の 4 つの手順は通常、バックエンドまたは運用およびメンテナンスによって完了され、QQ ログインが完了します。
テスト
テストに使用したappidとuriは次のとおりです(公式QQ認定に合格しました)
# appid :10055xxxx
# redirect_uri :http://www.corho.com:8080/#/login/callback
QQ ログイン機能の申請に成功したら、qq が提供する SDK ツールを使用してログイン関連機能を完了できます。
プロジェクトの共通使用
<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>
QC.Loginにより、ページ上にqqログインアイコンが自動生成され、 クリックするとジャンプすることができますが、エフェクトが表示されても指定したページにジャンプすることはできません
ログインをクリックした後に新しいウィンドウが開く問題を解決
生成されたコードは、img でラップされた a タグです。リンク全体を取得し、window.open などを削除するだけです。a リンクの Herf Jump のみが必要です。
<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>
2 つ目は、vue プロジェクトで使用される
(1) 導入と利用
複数のコンポーネントがログインするために qq を使用する必要がある場合があるため、各コンポーネントを直接インポートするのは面倒なので、 piublic/index.htmlに直接インポートすることはnpm i qcと同等です。
入力された data-appid と redirecturi は、このプロジェクト アプリケーションのテスト アカウントとパスワードです。
<script src="http://connect.qq.com/qc_jssdk.js" data-appid="xxx" data-redirecturi="http://www.corho.com:8080/#/login/callback"></script>
コンポーネントで使用される
import QC from 'qc'
<span id="qqLoginBtn"></span>
onMounted(() => {
// 组件渲染完毕,使用QC生成QQ登录按钮
QC.Login({
btnId: 'qqLoginBtn'
})
})
このステップを実行しない場合、qc は node_modules を検索しますが、npm がない場合、エラーが報告されます。
// 这个是设置外部扩展,模块为qc变量名为QC,导入qc将不做打包。
configureWebpack: {
externals: {
qc: 'QC'
}
},
Wepback に QC が外部拡張機能であることを伝えます。
-
import 'qc' が見つかった場合は、node_modules の下で探さないでください。
-
npm が build を実行するときは、qc をパッケージ化しないでください。
(2)自動生成コード変換・リンクジャンプ
デバッグツールでリンクを取得後、上記を全て削除します 申請後のIDがあることが前提です。
<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) テストアドレスをローカルにマッピングします。
ログイン後のコールバック ページはhttp://www.corho.com:8080/#/login/callbackです。このアドレスは localhost で始まっていません。ローカル アドレスではありません。
ホストを変更する
ドメイン名がwww.corho.comと localhost が矛盾しているため、ページをコールバックできず、ホスト アドレスをローカルで変更する必要があります。
ウィンドウズ
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') }
その後、指定されたルーティング コンポーネントに移動して操作を実行できます。
3. 着陸後の3つのルート
-
登録およびバインド済み ---> ログインに成功し、ホームページまたはソース ページにジャンプします
-
登録済み、バインドされていない、バインドされている携帯電話番号 ----> ログイン成功、ホームページまたはソース ページにジャンプ
-
未登録、アカウント情報が完了しました --> ログインに成功しました、ホームページまたはソース ページに移動します
背景知識
ログインしているかどうかを確認してください
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 でアクションを呼び出して情報を保存し、保存後にホームページにジャンプします。
失敗: キャッチに留まり、他の 2 つのルートを待ちます
<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>
2番目のルート
すでにアカウントをお持ちの場合は、携帯電話をバインドしてください。これは、現在のプロジェクトのアカウントをすでにお持ちで、携帯電話番号を直接バインドしていることを意味します。
ルート:
認証コードの取得: 1. 携帯電話番号の認証が正しいかどうかを確認します。 2. 認証コードを取得するためのインターフェイスを呼び出します。
バインディング インターフェイスを呼び出します。 1. ユーザー名と検証コードのフォーム検証が正しいかどうかを確認します。 2. インターフェイスを呼び出します。 3. プロンプト テキスト 4. ホーム ページにジャンプします。
<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>
3番目のルート
プロジェクトアカウントなし、携帯電話番号のバインドなし
ルート:
まずユーザー名を確認し、インターフェースを呼び出して現在のユーザー名が存在するかどうかを確認します。
2 つのパスワードが等しいことを確認します
認証コードの取得: 1. 携帯電話番号の認証が正しいかどうかを確認します。 2. 認証コードを取得するためのインターフェイスを呼び出します。
バインディング インターフェイスを呼び出します。 1. すべてのフォーム検証が正しいかどうか 2. インターフェイスを呼び出します 3. プロンプト テキスト 4. ホーム ページにジャンプします
<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>