• 第三方登录功能的实现之 QQ登录 - 已绑定账号


    目录

    登录流程梳理

    用户操作

     前置工作准备 - 了解

    电脑环境设置

    目的

    核心步骤

    验证效果 

    DNS 解析概念 - 了解

    QQ授权登录实现

    改进一下:不要跳转到新页面

     三方登录之后的判断逻辑

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

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

    3.登录成功后,跳转首页,或者来源页面

    QQ登录-基本结构和切换交互

    QQ登录 - 创建组件

     思路

     组件1 - 绑定手机

    组件2 - 完善信息

    QQ登录 - 已绑定账号

    思路

    补充类型声明

    QQ登录 - 未绑定 - 有账号

    QQ登录 - 未绑定 - 无账号


    现在越来越流行第三方登录,它在我们生活中是到处可见的,就比如QQ、微信扫码登录等等

    下面呐,就借用QQ登录来讲解是第三方登录是怎样实现的

            因为其他第三方登录的思路跟QQ登录思路相同

    登录流程梳理

    目标:掌握第三方登录的实现流程

    用户操作

    点击QQ登录  ---> 小兔仙跳转到QQ登录页--->扫码/用户名密码登录 --->登录成功 ---> 回跳目标页(是提前与QQ约定的)

     前置工作准备 - 了解

    1)参考文档

    1. 准备工作(opens new window)

         2.QQ互联JS_SDK(opens new window)

    2)大致步骤

    1. 准备一个已经备案的网站需要有QQ登录的逻辑(登录页面,回跳页面)
    2. 然后在QQ互联上进行身份认证,并且审核通过
    3. 在QQ互联上创建应用,应用需要域名,备案号,回调地址等
    4. 等待人工审核,审核通过会得到应用ID 应用key 回调地址
    5. 帮大家申请的结果如下:
    1. # 测试用 appid
    2. # 100556005
    3. # 测试用 redirect_uri
    4. # 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 项目。

    核心步骤

    1. 项目中准备页面及路由。配置 VueRoutervue 组件。
    2. 设置项目的访问地址为指定域名。修改 vite.config.ts 配置。
    3. 修改电脑的 host 文件。

    (1)修改vite.config.ts 配置。

    1. export default defineConfig({
    2. // 配置开发服务器
    3. server: {
    4. // QQ三方登录的回调uri为:http://www.corho.com:8080/#/login/callback
    5. // vite 中配置: www.corho.com:8080
    6. host: "www.corho.com",
    7. port: 8080,
    8. // 其他有价值的配置项
    9. open: true, // 帮我们打开浏览器
    10. cors: true, // 允许开发时 ajax 跨域
    11. },
    12. ...
    13. });

    (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

    1. <template>
    2. <h1>callback-QQ登录回跳页面测试h1>
    3. template>

            b。配置路由:

     绑定路由(一级路由)

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

     步骤验证:http://www.corho.com:8080/#/login/callback看到回调页面组件。

    DNS 解析概念 - 了解

    由于本地我们的网站是访问http://localhost:8080   =>  http://127.0.0.1:8080

    而回调地址的域名是http://www.corho.com:8080,俩个地址不一致是无法进行跳转的,

    需要我们修改本地的 hosts 文件,让域名访问时解析到我们本地的ip上

    DNS 解析:(网络中,服务器不认域名的,认的是 ipwww.jd.com

    1. 作用是将域名地址解析成ip地址
    2. 优先级 先以本地的 hosts 文件为主 然后才走线上的dns服务器

    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授权登录实现

     官网流程:QQ互联JS_SDK(opens new window)

    (1)在index.html中添加

    1. type="text/javascript"
    2. charset="utf-8"
    3. src="http://connect.qq.com/qc_jssdk.js"
    4. data-appid="100556005"
    5. data-redirecturi="http://www.corho.com:8080/#/login/callback"
    6. >
    7. <script type="text/javascript">
    8. QC.Login({
    9. btnId:"qqLoginBtn"//插入按钮的节点id
    10. });
    11. script>
    12. <span id="qqLoginBtn">span>

     上面的代码的作用是生成 登录按钮, 之后就可以删除这段代码!!

    现在就可以实现QQ的登录啦。

    改进一下:不要跳转到新页面

     window.open可以打开一个新的窗口 ===》 我们不需要!

     改进: 可以直接通过a标签指向这个地址

    具体代码

    在组件src/views/Login/components/LoginForm.vue中添加登录图标

    1. 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"
    2. ><img
    3. src="https://qzonestyle.gtimg.cn/qzone/vas/opensns/res/img/Connect_logo_7.png"
    4. alt="QQ登录"
    5. border="0"
    6. />

     三方登录之后的判断逻辑

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

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

        如果绑定过,完成登录

        没有绑定过

             · 有账号的,绑定手机号,即为登录

            ·  没账号的, 完善账户信息,即为登录

    3.登录成功后,跳转首页,或者来源页面

    QQ登录-基本结构和切换交互

    (1)准备结构

    1. <template>
    2. <LoginHeader>QQ登录LoginHeader>
    3. <section class="container">
    4. <nav class="tab">
    5. <a href="javascript:;">
    6. <i class="iconfont icon-bind" />
    7. <span>已有小兔鲜账号,请绑定手机span>
    8. a>
    9. <a href="javascript:;">
    10. <i class="iconfont icon-edit" />
    11. <span>没有小兔鲜账号,请完善资料span>
    12. a>
    13. nav>
    14. <div class="tab-content" v-if="true">绑定手机div>
    15. <div class="tab-content" v-else>完善资料div>
    16. section>
    17. <LoginFooter>LoginFooter>
    18. template>
    19. <style scoped lang="less">
    20. .container {
    21. padding: 25px 0;
    22. }
    23. .tab {
    24. background: #fff;
    25. height: 80px;
    26. padding-top: 40px;
    27. font-size: 18px;
    28. text-align: center;
    29. a {
    30. color: #666;
    31. display: inline-block;
    32. width: 350px;
    33. line-height: 40px;
    34. border-bottom: 2px solid #e4e4e4;
    35. i {
    36. font-size: 22px;
    37. vertical-align: middle;
    38. }
    39. span {
    40. vertical-align: middle;
    41. margin-left: 4px;
    42. }
    43. &.active {
    44. color: @xtxColor;
    45. border-color: @xtxColor;
    46. }
    47. }
    48. }
    49. .tab-content {
    50. min-height: 600px;
    51. background: #fff;
    52. }
    53. style>

    (2)切换效果

    1. <template>
    2. <LoginHeader>LoginHeader>
    3. <section class="container">
    4. <nav class="tab">
    5. <a
    6. + :class="{ active: hasAccount }"
    7. href="javascript:;"
    8. + @click="hasAccount = true"
    9. >
    10. <i class="iconfont icon-bind" />
    11. <span>已有小兔鲜账号,请绑定手机span>
    12. a>
    13. <a
    14. + :class="{ active: !hasAccount }"
    15. href="javascript:;"
    16. + @click="hasAccount = false"
    17. >
    18. <i class="iconfont icon-edit" />
    19. <span>没有小兔鲜账号,请完善资料span>
    20. a>
    21. nav>
    22. + <div class="tab-content" v-if="hasAccount">绑定手机div>
    23. + <div class="tab-content" v-else>完善资料div>
    24. section>
    25. <LoginFooter>LoginFooter>
    26. template>

    QQ登录 - 创建组件

     思路

    这两种情况对应不同的表单,所以这里分别封装成两个小的组件

     组件1 - 绑定手机

    src/views/Login/components/CallbackBind.vue 绑定手机

    1. <template>
    2. <div class="xtx-form">
    3. <div class="user-info">
    4. <img
    5. src="http://qzapp.qlogo.cn/qzapp/101941968/57C7969540F9D3532451374AA127EE5B/50"
    6. alt=""
    7. />
    8. <p>Hi,Tom 欢迎来小兔鲜,完成绑定后可以QQ账号一键登录哦~p>
    9. div>
    10. <div class="xtx-form-item">
    11. <div class="field">
    12. <i class="icon iconfont icon-phone">i>
    13. <input class="input" type="text" placeholder="绑定的手机号" />
    14. div>
    15. <div class="error">div>
    16. div>
    17. <div class="xtx-form-item">
    18. <div class="field">
    19. <i class="icon iconfont icon-code">i>
    20. <input class="input" type="text" placeholder="短信验证码" />
    21. <span class="code">发送验证码span>
    22. div>
    23. <div class="error">div>
    24. div>
    25. <a href="javascript:;" class="submit">立即绑定a>
    26. div>
    27. template>
    28. <style scoped lang="less">
    29. .user-info {
    30. width: 320px;
    31. height: 70px;
    32. margin: 0 auto;
    33. display: flex;
    34. background: #f2f2f2;
    35. align-items: center;
    36. padding: 0 10px;
    37. margin-bottom: 25px;
    38. img {
    39. background: #f2f2f2;
    40. width: 50px;
    41. height: 50px;
    42. }
    43. p {
    44. padding-left: 10px;
    45. }
    46. }
    47. .code {
    48. position: absolute;
    49. right: 0;
    50. top: 0;
    51. line-height: 50px;
    52. width: 80px;
    53. color: #999;
    54. &:hover {
    55. cursor: pointer;
    56. }
    57. }
    58. style>

    组件2 - 完善信息

     src/views/Login/components/CallbackPatch.vue 完善信息

    1. <template>
    2. <div class="xtx-form">
    3. <div class="xtx-form-item">
    4. <div class="field">
    5. <i class="icon iconfont icon-user">i>
    6. <input class="input" type="text" placeholder="请输入用户名" />
    7. div>
    8. <div class="error">div>
    9. div>
    10. <div class="xtx-form-item">
    11. <div class="field">
    12. <i class="icon iconfont icon-phone">i>
    13. <input class="input" type="text" placeholder="请输入手机号" />
    14. div>
    15. <div class="error">div>
    16. div>
    17. <div class="xtx-form-item">
    18. <div class="field">
    19. <i class="icon iconfont icon-code">i>
    20. <input class="input" type="text" placeholder="请输入验证码" />
    21. <span class="code">发送验证码span>
    22. div>
    23. <div class="error">div>
    24. div>
    25. <div class="xtx-form-item">
    26. <div class="field">
    27. <i class="icon iconfont icon-lock">i>
    28. <input class="input" type="password" placeholder="请输入密码" />
    29. div>
    30. <div class="error">div>
    31. div>
    32. <div class="xtx-form-item">
    33. <div class="field">
    34. <i class="icon iconfont icon-lock">i>
    35. <input class="input" type="password" placeholder="请确认密码" />
    36. div>
    37. <div class="error">div>
    38. div>
    39. <a href="javascript:;" class="submit">立即提交a>
    40. div>
    41. template>
    42. <style scoped lang="less">
    43. .code {
    44. position: absolute;
    45. right: 0;
    46. top: 0;
    47. line-height: 50px;
    48. width: 80px;
    49. color: #999;
    50. &:hover {
    51. cursor: pointer;
    52. }
    53. }
    54. style>

    渲染组件

    1. <template>
    2. <LoginHeader>LoginHeader>
    3. <section class="container">
    4. <nav class="tab">
    5. <a
    6. :class="{ active: hasAccount }"
    7. href="javascript:;"
    8. @click="hasAccount = true"
    9. >
    10. <i class="iconfont icon-bind" />
    11. <span>已有小兔鲜账号,请绑定手机span>
    12. a>
    13. <a
    14. :class="{ active: !hasAccount }"
    15. href="javascript:;"
    16. @click="hasAccount = false"
    17. >
    18. <i class="iconfont icon-edit" />
    19. <span>没有小兔鲜账号,请完善资料span>
    20. a>
    21. nav>
    22. <div class="tab-content" v-if="hasAccount">
    23. + <CallbackBind>CallbackBind>
    24. div>
    25. <div class="tab-content" v-else>
    26. + <CallbackPatch>CallbackPatch>
    27. div>
    28. section>
    29. <LoginFooter>LoginFooter>
    30. template>

    QQ登录 - 已绑定账号

    QQ登录之后会有三种情况需要处理

    1. 该QQ账号已经绑定过小兔鲜账号,直接跳转到首页
    2. 该QQ账号没有绑定有账号

                        a:有账号,直接绑定QQ号

                        b:没有账号,完善注册信息并绑定QQ号

    思路

    1. 回跳组件初始化的时候根据QQ的接口获取openId
    2. 根据openId去自己后台尝试进行登录
    3. 如果成功,就代表已注册已绑定,记录返回的用户信息,跳转到首页或者来源页面

    js dk公开方法

    OpenAPI调用说明_OAuth2.0 — QQ互联WIKI

    1. QC.Login.check() 检查此时QQ是否已经登录
    2. QC.Login.getMe() 获取用户标识openId 将来传给userQQLogin作为第一个参数
    3. QC.api("get_user_info") 获取用户资料

    补充类型声明

    新增QC的类型声明 在文件中 env.d.ts

    直接使用QC在TS中会报错,因为TS无法识别QC,且QQ第三方登录默认是不支持ts的,需要自定义命名空间来实现该效果。

    1. declare namespace QC {
    2. const Login: {
    3. /**
    4. * 检查QQ是否登录成功
    5. */
    6. check: () => boolean
    7. /**
    8. * 获取openId
    9. */
    10. getMe: (callback: (openId: string) => void) => void
    11. }
    12. const api: (api: 'get_user_info') => { success: (res: any) => void }
    13. }

    (2)确认当前QQ是否登录成功

    1. // 获取用户信息
    2. const isLogin = QC.Login.check()
    3. console.log(isLogin)

    (3)获取openid

    1. // 1. 判断用户是否登录
    2. const isLogin = QC.Login.check()
    3. // console.log(isLogin)
    4. if (isLogin) {
    5. // 2. 获取openId
    6. QC.Login.getMe((openId) => {
    7. console.log(openId)
    8. })
    9. }

    (4)封装方法,使用QQ登录

     source: 1为pc,2为webapp,3为微信小程序, 4为Android, 5为ios, 6为qq, 7为微信

    1. // source: 1为pc,2为webapp,3为微信小程序, 4为Android, 5为ios, 6为qq, 7为微信
    2. async qqLogin(openId: string) {
    3. const res = await request.post<IApiRes<Profile>>('/login/social', {
    4. unionId: openId,
    5. source: 6
    6. })
    7. // 1. 保存用户信息到 state 中
    8. this.profile = res.data.result
    9. setProfile(res.data.result)
    10. },

    (5)登录成功

    1. // 1. 判断用户是否登录
    2. const isLogin = QC.Login.check()
    3. // console.log(isLogin)
    4. if (isLogin) {
    5. // 2. 获取openId
    6. QC.Login.getMe(async (openId) => {
    7. // 3. 发送请求进行QQ登录
    8. await user.qqLogin(openId)
    9. Message.success('登录成功')
    10. router.push('/')
    11. })
    12. }

    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