目录
1.在登录页面, QQ登录按钮处,赋予其打开QQ登录页面功能
2. 回跳的页面得到QQ给的唯一标识 openId,此时表示QQ已经认可TA: TA是QQ家的用户,但是,是不是我们系统的用户呢? 根据openId去后台查询是否已经绑定过账户
现在越来越流行第三方登录,它在我们生活中是到处可见的,就比如QQ、微信扫码登录等等
下面呐,就借用QQ登录来讲解是第三方登录是怎样实现的
因为其他第三方登录的思路跟QQ登录思路相同
目标:掌握第三方登录的实现流程
点击QQ登录 ---> 小兔仙跳转到QQ登录页--->扫码/用户名密码登录 --->登录成功 ---> 回跳目标页(是提前与QQ约定的)

1)参考文档
2.QQ互联JS_SDK(opens new window)
2)大致步骤
身份认证,并且审核通过应用ID 应用key 回调地址- # 测试用 appid
- # 100556005
- # 测试用 redirect_uri
- # http://www.corho.com:8080/#/login/callback
那问题来了
1.这个申请工作一般由谁去做?
公司的运维(负责管理公司账号的人)
2.申请下来的id,应用key,回调地址url能改吗?
a.都不能修改,负责无效
b.回调地址 uri 的包含四部分: 1. 域名,2. 端口号 3. 哈希路由模式 4. 路由地址 都必须完全一致,否则不能展示。
3.回调url打开看不到内容?
http://www.corho.com:8080/#/login/callback
a.修改vite.config.ts 配置。
b.修改电脑的 host 文件,访问本地服务器。
c.配置VueRouter路由 和 vue 组件。
就是让浏览器访问http://www.corho.com:8080/#/login/callback 地址,能打开正在开发的 Vue 项目。
VueRouter 和 vue 组件。vite.config.ts 配置。host 文件。(1)修改vite.config.ts 配置。
- export default defineConfig({
- // 配置开发服务器
- server: {
- // QQ三方登录的回调uri为:http://www.corho.com:8080/#/login/callback
- // vite 中配置: www.corho.com:8080
- host: "www.corho.com",
- port: 8080,
- // 其他有价值的配置项
- open: true, // 帮我们打开浏览器
- cors: true, // 允许开发时 ajax 跨域
- },
- ...
- });
(2)修改host文件
Windows系统
提醒:修改电脑配置,需要先退出 360 或 各种管家 各种 杀毒软件
提醒:如果修改 hosts 文件有弹窗警告,点击信任(因为这是我们自己进行的安全操作)
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 回车即可
浏览器访问 http://www.corho.com:8080/#/ 能看到自己开发的 Vue3 项目表示第二步配置成功。
(3)配置路由和组件
a。新建组件: views/Login/Callback.vue
-
- <template>
- <h1>callback-QQ登录回跳页面测试h1>
- template>
b。配置路由:
绑定路由(一级路由)
{
path: '/login/callback',
component: () => import('@/views/login/callback.vue')
}
步骤验证:http://www.corho.com:8080/#/login/callback看到回调页面组件。
由于本地我们的网站是访问http://localhost:8080 => http://127.0.0.1:8080
而回调地址的域名是http://www.corho.com:8080,俩个地址不一致是无法进行跳转的,
需要我们修改本地的 hosts 文件,让域名访问时解析到我们本地的ip上
DNS 解析:(网络中,服务器不认域名的,认的是 ip) www.jd.com
DSN解析说明
DNS解析: 将域名解析成ip地址的过程。
想看一个网站 www.jd.com => 电脑不知道什么是 www.jd.com,需要询问的
1.先问本地hosts文件(一般不改) 如果本地配置了 域名 和 地址的映射关系,优先使用 hosts 中的映射
127.0.0.1 www.jd.com
2.如果本地hosts文件里面没配(默认一般都没配)比如:找www.baidu.com
会找线上的 dns 服务器, dns 服务器就像一个字典,
字典中记录大量的 网站域名 和 网站ip 的对应关系dns 服务器
112.80.248.75 www.baidu.com
xxx.xx.xxx.xx www.xxx.com

官网流程:QQ互联JS_SDK(opens new window)
(1)在index.html中添加
- type="text/javascript"
- charset="utf-8"
- src="http://connect.qq.com/qc_jssdk.js"
- data-appid="100556005"
- data-redirecturi="http://www.corho.com:8080/#/login/callback"
- >
- <script type="text/javascript">
- QC.Login({
- btnId:"qqLoginBtn"//插入按钮的节点id
- });
- script>
- <span id="qqLoginBtn">span>

上面的代码的作用是生成 登录按钮, 之后就可以删除这段代码!!
现在就可以实现QQ的登录啦。
改进一下:不要跳转到新页面

window.open可以打开一个新的窗口 ===》 我们不需要!
改进: 可以直接通过a标签指向这个地址
具体代码
在组件src/views/Login/components/LoginForm.vue中添加登录图标
- href="https://graph.qq.com/oauth2.0/authorize?client_id=100556005&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"
- />
三方登录之后的判断逻辑



1.在登录页面, QQ登录按钮处,赋予其打开QQ登录页面功能

2. 回跳的页面得到QQ给的唯一标识 openId,此时表示QQ已经认可TA: TA是QQ家的用户,但是,是不是我们系统的用户呢? 根据openId去后台查询是否已经绑定过账户

如果绑定过,完成登录
没有绑定过
· 有账号的,绑定手机号,即为登录
· 没账号的, 完善账户信息,即为登录
3.登录成功后,跳转首页,或者来源页面
QQ登录-基本结构和切换交互
(1)准备结构
-
- <template>
- <LoginHeader>QQ登录LoginHeader>
- <section class="container">
- <nav class="tab">
- <a href="javascript:;">
- <i class="iconfont icon-bind" />
- <span>已有小兔鲜账号,请绑定手机span>
- a>
- <a href="javascript:;">
- <i class="iconfont icon-edit" />
- <span>没有小兔鲜账号,请完善资料span>
- a>
- nav>
- <div class="tab-content" v-if="true">绑定手机div>
- <div class="tab-content" v-else>完善资料div>
- section>
- <LoginFooter>LoginFooter>
- template>
-
- <style scoped lang="less">
- .container {
- padding: 25px 0;
- }
- .tab {
- background: #fff;
- height: 80px;
- padding-top: 40px;
- font-size: 18px;
- text-align: center;
- a {
- color: #666;
- display: inline-block;
- width: 350px;
- line-height: 40px;
- border-bottom: 2px solid #e4e4e4;
- i {
- font-size: 22px;
- vertical-align: middle;
- }
- span {
- vertical-align: middle;
- margin-left: 4px;
- }
- &.active {
- color: @xtxColor;
- border-color: @xtxColor;
- }
- }
- }
- .tab-content {
- min-height: 600px;
- background: #fff;
- }
- style>
(2)切换效果
-
- <template>
- <LoginHeader>LoginHeader>
- <section class="container">
- <nav class="tab">
- <a
- + :class="{ active: hasAccount }"
- href="javascript:;"
- + @click="hasAccount = true"
- >
- <i class="iconfont icon-bind" />
- <span>已有小兔鲜账号,请绑定手机span>
- a>
- <a
- + :class="{ active: !hasAccount }"
- href="javascript:;"
- + @click="hasAccount = false"
- >
- <i class="iconfont icon-edit" />
- <span>没有小兔鲜账号,请完善资料span>
- a>
- nav>
- + <div class="tab-content" v-if="hasAccount">绑定手机div>
- + <div class="tab-content" v-else>完善资料div>
- section>
- <LoginFooter>LoginFooter>
- template>
QQ登录 - 创建组件
思路
这两种情况对应不同的表单,所以这里分别封装成两个小的组件


组件1 - 绑定手机
src/views/Login/components/CallbackBind.vue 绑定手机
- <template>
- <div class="xtx-form">
- <div class="user-info">
- <img
- src="http://qzapp.qlogo.cn/qzapp/101941968/57C7969540F9D3532451374AA127EE5B/50"
- alt=""
- />
- <p>Hi,Tom 欢迎来小兔鲜,完成绑定后可以QQ账号一键登录哦~p>
- div>
- <div class="xtx-form-item">
- <div class="field">
- <i class="icon iconfont icon-phone">i>
- <input class="input" type="text" placeholder="绑定的手机号" />
- div>
- <div class="error">div>
- div>
- <div class="xtx-form-item">
- <div class="field">
- <i class="icon iconfont icon-code">i>
- <input class="input" type="text" placeholder="短信验证码" />
- <span class="code">发送验证码span>
- div>
- <div class="error">div>
- div>
- <a href="javascript:;" class="submit">立即绑定a>
- div>
- template>
-
- <style scoped lang="less">
- .user-info {
- width: 320px;
- height: 70px;
- margin: 0 auto;
- display: flex;
- background: #f2f2f2;
- align-items: center;
- padding: 0 10px;
- margin-bottom: 25px;
- img {
- background: #f2f2f2;
- width: 50px;
- height: 50px;
- }
- p {
- padding-left: 10px;
- }
- }
- .code {
- position: absolute;
- right: 0;
- top: 0;
- line-height: 50px;
- width: 80px;
- color: #999;
- &:hover {
- cursor: pointer;
- }
- }
- style>
组件2 - 完善信息
src/views/Login/components/CallbackPatch.vue 完善信息
- <template>
- <div class="xtx-form">
- <div class="xtx-form-item">
- <div class="field">
- <i class="icon iconfont icon-user">i>
- <input class="input" type="text" placeholder="请输入用户名" />
- div>
- <div class="error">div>
- div>
- <div class="xtx-form-item">
- <div class="field">
- <i class="icon iconfont icon-phone">i>
- <input class="input" type="text" placeholder="请输入手机号" />
- div>
- <div class="error">div>
- div>
- <div class="xtx-form-item">
- <div class="field">
- <i class="icon iconfont icon-code">i>
- <input class="input" type="text" placeholder="请输入验证码" />
- <span class="code">发送验证码span>
- div>
- <div class="error">div>
- div>
- <div class="xtx-form-item">
- <div class="field">
- <i class="icon iconfont icon-lock">i>
- <input class="input" type="password" placeholder="请输入密码" />
- div>
- <div class="error">div>
- div>
- <div class="xtx-form-item">
- <div class="field">
- <i class="icon iconfont icon-lock">i>
- <input class="input" type="password" placeholder="请确认密码" />
- div>
- <div class="error">div>
- div>
- <a href="javascript:;" class="submit">立即提交a>
- div>
- template>
-
- <style scoped lang="less">
- .code {
- position: absolute;
- right: 0;
- top: 0;
- line-height: 50px;
- width: 80px;
- color: #999;
- &:hover {
- cursor: pointer;
- }
- }
- style>
渲染组件
-
- <template>
- <LoginHeader>LoginHeader>
- <section class="container">
- <nav class="tab">
- <a
- :class="{ active: hasAccount }"
- href="javascript:;"
- @click="hasAccount = true"
- >
- <i class="iconfont icon-bind" />
- <span>已有小兔鲜账号,请绑定手机span>
- a>
- <a
- :class="{ active: !hasAccount }"
- href="javascript:;"
- @click="hasAccount = false"
- >
- <i class="iconfont icon-edit" />
- <span>没有小兔鲜账号,请完善资料span>
- a>
- nav>
- <div class="tab-content" v-if="hasAccount">
- + <CallbackBind>CallbackBind>
- div>
- <div class="tab-content" v-else>
- + <CallbackPatch>CallbackPatch>
- div>
- section>
- <LoginFooter>LoginFooter>
- template>
QQ登录 - 已绑定账号
QQ登录之后会有三种情况需要处理
- 该QQ账号已经绑定过小兔鲜账号,直接跳转到首页
- 该QQ账号没有绑定有账号
a:有账号,直接绑定QQ号
b:没有账号,完善注册信息并绑定QQ号
思路
- 回跳组件初始化的时候根据QQ的接口获取openId
- 根据openId去自己后台尝试进行登录
- 如果成功,就代表已注册已绑定,记录返回的用户信息,跳转到首页或者来源页面
js dk公开方法
OpenAPI调用说明_OAuth2.0 — QQ互联WIKI
- QC.Login.check() 检查此时QQ是否已经登录
- QC.Login.getMe() 获取用户标识openId 将来传给userQQLogin作为第一个参数
- QC.api("get_user_info") 获取用户资料
补充类型声明
新增QC的类型声明 在文件中 env.d.ts
直接使用QC在TS中会报错,因为TS无法识别QC,且QQ第三方登录默认是不支持ts的,需要自定义命名空间来实现该效果。
- declare namespace QC {
- const Login: {
- /**
- * 检查QQ是否登录成功
- */
- check: () => boolean
- /**
- * 获取openId
- */
- getMe: (callback: (openId: string) => void) => void
- }
- const api: (api: 'get_user_info') => { success: (res: any) => void }
- }
(2)确认当前QQ是否登录成功
- // 获取用户信息
- const isLogin = QC.Login.check()
- console.log(isLogin)
(3)获取openid
- // 1. 判断用户是否登录
- const isLogin = QC.Login.check()
- // console.log(isLogin)
- if (isLogin) {
- // 2. 获取openId
- QC.Login.getMe((openId) => {
- console.log(openId)
- })
- }
(4)封装方法,使用QQ登录
source: 1为pc,2为webapp,3为微信小程序, 4为Android, 5为ios, 6为qq, 7为微信
- // source: 1为pc,2为webapp,3为微信小程序, 4为Android, 5为ios, 6为qq, 7为微信
- async qqLogin(openId: string) {
- const res = await request.post<IApiRes<Profile>>('/login/social', {
- unionId: openId,
- source: 6
- })
- // 1. 保存用户信息到 state 中
- this.profile = res.data.result
- setProfile(res.data.result)
- },
(5)登录成功
- // 1. 判断用户是否登录
- const isLogin = QC.Login.check()
- // console.log(isLogin)
- if (isLogin) {
- // 2. 获取openId
- QC.Login.getMe(async (openId) => {
- // 3. 发送请求进行QQ登录
- await user.qqLogin(openId)
- Message.success('登录成功')
- router.push('/')
- })
- }
QQ登录 - 未绑定 - 有账号
QQ登录 - 未绑定 - 无账号
-
相关阅读:
文心一言 VS 讯飞星火 VS chatgpt (122)-- 算法导论10.4 3题
CentOS8服务器时间同步
关于SQL优化的辟谣
道可云元宇宙每日资讯|《江苏省元宇宙产业发展行动计划》发布
微信支付系统
有必要发这篇文章了!
前端开发:Mac电脑安装grunt构建工具的方法
Hbase 协处理器
App Languages 批量化导入iOS多语言
linux study01
-
原文地址:https://blog.csdn.net/LJM51200/article/details/126551120