当前位置: 首页 > news >正文

【vue+nestjs】qq第三方授权登录【超详细】

项目场景:

前端使用vue3+ts 后端使用nestjs


1.申请appId,appKey

1.进入qq互联官网。创建应用
在这里插入图片描述
特别注意
1.在填写网站回调域时,需要你线上真实能访问的。不然审核不通过。我的回调地址是前端路由地址
2.如果你想本地调试,回调到你的线上地址。你可以在本地设置本地域名,做反向代理。我是用的是phpstudy,方向代理自己的线上域名。

如果你还是不明白,可以留言

2.代码演示

特别注意:
如果你跟我一样是前后端分离的模式开发的,应用回调地址填写的应该是你的前端路由地址。在你的前端页面获取code,把code值传给后端接口。后端接口通过code获取gitee用户信息。

代码演示

我的应用回调地址:http://localhost:8080/vuecms/qq

  1. 前端点击qq图标登录代码:
<div @click="handleToLogin('qq')">gitee
</div>const handleToLogin = (type:string)=>{window.location.href="http://localhost:3000/user/oauth/qq"
}
  1. http://localhost:3000/user/oauth/qq后端接口代码
	@Get('/oauth/qq')async qqLogin(@Res() response: Response) {let appId = 你的appId;let redirectUrl = 你的回调地址;const state = Date.now()let scope = "get_user_info,list_album"return qqOauthConfig.authorizeUrl+`&client_id=${appId}&redirect_uri=${redirectUrl}&state=${state}&scope=${scope}`;}
  1. 回调地址前端代码
<template><div class="u-f u-f-ac u-f-ajc" style="width: 100%;height:100vh"><template v-if="isOauth"><el-resulticon="success"title="授权成功,跳转中..."></el-result></template><template v-else><el-resulticon="error"title="授权失败"></el-result></template></div>
</template><script setup lang="ts">import {useRoute,useRouter} from "vue-router";import {onMounted} from "@vue/runtime-core";import {requestGiteeLogin} from "@/network/common/oauthPage";import {setToken, setUserId, setUsername} from "@/utils/storage";import {handleGetCurInstance} from "@/utils/utils";import {ref} from "vue"let route = useRoute()let router = useRouter()let query = route.query;let {model} = handleGetCurInstance()let isOauth = ref(true)onMounted(()=>{//获取返回的code,通过code对后端发起请求,获取qq用户信息let {code,state} = query;let form = {code,state}requestQQLogin(form).then(res=>{let {data,code,message} = res;if(code==200){setToken(data.token)setUserId(data.id)setUsername(data.username)window.location.href="/"}else{model.handleMsg(message,"warning")isOauth.value =false;}})})
</script>
  1. requestQQLogin请求的后端代码
// qq 的认证配置
export const qqOauthConfig = {cid: "",//gitee官网设置获取secret: "",redirectURL: '',//gitee官网配置进行填写authorizeUrl: 'https://graph.qq.com/oauth2.0/authorize?response_type=code',getAccessTokenUrl: 'https://graph.qq.com/oauth2.0/token?grant_type=authorization_code',openId:"https://graph.qq.com/oauth2.0/me",qqUserAPI:"https://graph.qq.com/user/get_user_info"
};
	//qq登录@Post('/oauth/qqLogin')async getQQInfo(@Body() qqLoginDto:QqLoginDto,@IpAddress() clientIp: string) {let {code,operationSystem,browser} = giteeLoginDtolet accessToken:any = await this.handleGetQQAccessToken(code)if(!accessToken.data){return this.msgService.fail("code过期,请重新登录")}let giteeInfo:any = await this.getQQInfoByAccessToken(accessToken.data.accessToken,accessToken.data.appId);if(!giteeInfo.data){return this.msgService.fail("获取qq账号信息失败")}let { nickname } = giteeInfo.data.userData;let clientId = 0;let qqId = sysConfigEnum.qqLoginConfig + JSON.parse(JSON.stringify(giteeInfo.data.openid));//判断qq是否有关联账号。如果有就登陆,没有就新创建一个账号let userNum = await this.userEntity.createQueryBuilder().where({ qqId:qqId }).getCount()let username;//没有账号,注册帐号if(userNum<=0){let roleData = await this.roleEntity.createQueryBuilder().where({roleName:"试用角色"}).getOne()username = handleGetCode(8);username = await this.handleGetUsername(username);let originalPwd = handleGetCode(8);let password = JSON.parse(JSON.stringify(originalPwd))password = securityMd5(password)let userData;try {userData = await this.userEntity.createQueryBuilder().insert().values({username,originalPwd,password,qqId:qqId,roleId:roleData.id}).execute();}catch (error) {throw new HttpException(error,HttpStatus.SERVICE_UNAVAILABLE)}clientId = userData.identifiers[0]["id"]}else{let userData = await this.userEntity.createQueryBuilder().where({qqId:qqId}).getOne()username = userData.usernameclientId = userData.id;}let ip  = handleDealIpv6ToIpv4(clientIp)let token = this.authService.createToken({id:clientId,username,ip})await this.updateUserInfoStatus(clientId,token,ip,operationSystem,browser)return {id:clientId,username,token}}//获取gitee的accessTokenasync handleGetQQAccessToken(code:string):Promise<resInterface>{let key = sysConfigEnum.qqLoginConfiglet data = await this.sysConfigService.handleGetSysData(key)if(!data.appId || !data.appKey || !data.redirectUrl){return {data:false,msg:""};}let appId = data.appId;let appKey = data.appKey;let redirectUrl = data.redirectUrl;//回调路劲获取codelet authData = await axios.get(qqOauthConfig.getAccessTokenUrl+`&code=${code}&client_id=${appId}&client_secret=${appKey}&redirect_uri=${redirectUrl}`).then(res=>{let resArr = res.data.split("&")let accessToken = resArr[0].split("=")[1]let expiresIn = resArr[1].split("=")[1]let refreshToken = resArr[2].split("=")[1]return {accessToken,expiresIn,refreshToken};}).catch(err=>{return err.data})if(authData?.error){return this.msgService.commonRes(false,authData?.error?.error_description);}else{return this.msgService.commonRes({accessToken:authData?.accessToken,appId},"");}}//通过access_token获取gitee信息async getQQInfoByAccessToken(accessToken: boolean | string,appId:string){let authData = await axios.get(qqOauthConfig.openId+`?access_token=${accessToken}`).then(res=>{let data = JSON.parse(res.data.substring(9, res.data.length-3))let clientId = data.client_id;let openid = data.openid;return {clientId,openid};}).catch(err=>{return err.data})if(authData?.error){return this.msgService.commonRes(false,authData?.error?.error_description);}let userData = await axios.get(qqOauthConfig.qqUserAPI+`?access_token=${accessToken}&oauth_consumer_key=${appId}&openid=${authData.openid}`).then(res=>{return res.data;}).catch(err=>{return err.data})if(userData?.error){return this.msgService.commonRes(false,authData?.error?.error_description);}else{return this.msgService.commonRes({userData,openid:authData.openid},"");}}

3.特别注意

如果以上步骤都没问题。需要把本地测试回调地址改为线上路径

如果你还是不懂,你可以克隆下我的项目。开源免费。如果对你有帮助,给我一个star就行了
https://gitee.com/derekgo/vue-cms_xg

踩坑不易,还希望各位大佬支持一下 \textcolor{gray}{踩坑不易,还希望各位大佬支持一下} 踩坑不易,还希望各位大佬支持一下

📃 个人主页: \textcolor{green}{个人主页:} 个人主页: 沉默小管

📃 个人网站: \textcolor{green}{个人网站:} 个人网站: 沉默小管

📃 个人导航网站: \textcolor{green}{个人导航网站:} 个人导航网站: 沉默小管导航网

📃 我的开源项目: \textcolor{green}{我的开源项目:} 我的开源项目: vueCms.cn

🔥 技术交流 Q Q 群: 837051545 \textcolor{green}{技术交流QQ群:837051545} 技术交流QQ群:837051545

👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

如果有不懂可以留言,我看到了应该会回复
如有错误,请多多指教

相关文章:

【vue+nestjs】qq第三方授权登录【超详细】

项目场景&#xff1a; 前端使用vue3ts 后端使用nestjs 1.申请appId,appKey 1.进入qq互联官网。创建应用 特别注意 1.在填写网站回调域时,需要你线上真实能访问的。不然审核不通过。我的回调地址是前端路由地址 2.如果你想本地调试&#xff0c;回调到你的线上地址。你可以在本…...

经典卷积神经网络 - VGG

使用块的网络 - VGG。 使用多个 3 3 3\times 3 33的要比使用少个 5 5 5\times 5 55的效果要好。 VGG全称是Visual Geometry Group&#xff0c;因为是由Oxford的Visual Geometry Group提出的。AlexNet问世之后&#xff0c;很多学者通过改进AlexNet的网络结构来提高自己的准确…...

系统集成测试(SIT)/系统测试(ST)/用户验收测试(UAT)

文章目录 单元测试集成测试系统测试用户验收测试黑盒测试白盒测试压力测试性能测试容量测试安全测试SIT和UAT的区别 单元测试 英文 unit testing&#xff0c;缩写 UT。测试粒度最小&#xff0c;一般由开发小组采用白盒方式来测试&#xff0c;主要测试单元是否符合“设计”。 …...

Android Gradle8.0以上多渠道写法以及针对不同渠道导入包的方式,填坑!

目录 多渠道的写法 针对多渠道引用不同的包 There was a failure while populating the build operation queue: Could not stat file E:\xxxx\xxxx\xxxx\app\src\UAT\libsUAT\xxx-provider(?)-xx.aar 最近升级了Gradle8.3之后&#xff0c;从Groovy 迁移到 Kotlin&#xff…...

hdlbits系列verilog解答(向量门操作)-14

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 构建一个具有两个 3 位输入的电路&#xff0c;用于计算两个向量的按位 OR、两个向量的逻辑 OR 以及两个向量的逆 &#xff08;NOT&#xff09;。将b反相输出到out_not上半部分&#xff0c;将a 的反相输出到out…...

工厂模式(初学)

工厂模式 1、简单工厂模式 是一种创建型设计模式&#xff0c;旨在通过一个工厂类&#xff08;简单工厂&#xff09;来封装对象的实例化过程 运算类 public class Operation { //这个是父类private double num1; //运算器中的两个值private double num2;public double getNu…...

python试题实例

背景&#xff1a; 在外地出差&#xff0c;突然接到单位电话&#xff0c;让自己出一些python考题供新人教育训练使用&#xff0c;以下是10道Python编程试题及其答案&#xff1a; 1.试题&#xff1a;请写一个Python程序&#xff0c;计算并输出1到100之间所有偶数的和。 答案&am…...

Java Heap Space问题解析与解决方案(InsCode AI 创作助手)

Heap Space问题是Java开发中常见的内存溢出问题之一&#xff0c;我们需要理解其原因和表现形式&#xff0c;然后通过优化代码、增加JVM内存和使用垃圾回收机制等方法来解决。 一、常见报错 java.lang.OutOfMemoryError: Java heap space二、Heap Space问题的原因 对象创建过…...

基于遥感影像的分类技术(监督/非监督和面向对象的分类技术)

遥感图像分类技术 “图像分类是将土地覆盖类别分配给像素的过程。例如&#xff0c;类别包括水、城市、森林、农业和草原。”前言 – 人工智能教程 什么是遥感图像分类&#xff1f; 遥感图像分类技术的三种主要类型是&#xff1a; 无监督图像分类监督图像分类基于对象的图像分析…...

插入兄弟元素 insertAfter() 方法

insertAfter() 方法在被选元素后插入 HTML 元素。 提示&#xff1a;如需在被选元素前插入 HTML 元素&#xff0c;请使用 insertBefore() 方法。 语法 $(content).insertAfter(selector)例子&#xff1a; $("<span>Hello world!</span>").insertAfter(…...

【C++项目】高并发内存池第二讲中心缓存CentralCache框架+核心实现

CentralCache 1.框架介绍2.核心功能3.核心函数实现介绍3.1SpanSpanList介绍3.2CentralCache.h3.3CentralCache.cpp3.4TreadCache申请内存函数介绍3.5慢反馈算法 1.框架介绍 回顾一下ThreadCache的设计&#xff1a; 如图所示&#xff0c;ThreadCache设计是一个哈希桶结构&…...

Git基础教程

一、Git简介 1、什么是Git&#xff1f; Git是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或大或小的项目。 Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源代码的版本控制软件。 Git与常用的版本控制工具CVS、Subversion等不同&#…...

stm32外部时钟为12MHZ,修改代码适配

代码默认是8MHZ的&#xff0c;修改2个地方&#xff1a; 第一个地方是这个文件的这里&#xff1a; 第二个地方是找到这个函数&#xff1a; 修改第二个地方的这里&#xff1a;...

【数据结构】八大排序

目录 1. 排序的概念及其作用 1.1 排序的概念 1.2 排序运用 1.3 常见的排序算法 2. 常见排序算法的实现 2.1 插入排序 2.1.1 基本思想 2.1.2 直接插入排序 2.1.3 希尔排序&#xff08;缩小增量排序&#xff09; 2.2 选择排序 2.2.1 基本思想 2.2.2 直接选择排序 2.2…...

MYSQL(事务+锁+MVCC+SQL执行流程)理解

一)事务的特性: 一致性:主要是在数据层面来说&#xff0c;不能说执行扣减库存的操作的时候用户订单数据却没有生成 原子性:主要是在操作层面来说&#xff0c;要么操作完成&#xff0c;要么操作全部回滚&#xff1b; 隔离性:是自己的事务操作自己的数据&#xff0c;不会受到到其…...

解密一致性哈希算法:实现高可用和负载均衡的秘诀

解密一致性哈希算法&#xff1a;实现高可用和负载均衡的秘诀 前言第一&#xff1a;分布式系统中的数据分布问题&#xff0c;为什么需要一致性哈希算法第二&#xff1a;一致性hash算法的原理第三&#xff1a;一致性哈希算法的优点和局限性第四&#xff1a;一致性哈希算法的安全性…...

Python脚本:让工作自动化起来

Python是一种流行的编程语言&#xff0c;以其简洁和易读性而闻名。它提供了大量的库和模块&#xff0c;使其成为自动化各种任务的绝佳选择。 本文将探讨Python脚本及其代码&#xff0c;可以帮助您自动化各种任务并提高工作效率。无论您是开发人员、数据分析师还是只是想简化工…...

香港科技大学广州|可持续能源与环境学域博士招生宣讲会—广州大学城专场!!!(暨全额奖学金政策)

香港科技大学广州&#xff5c;可持续能源与环境学域博士招生宣讲会—广州大学城专场&#xff01;&#xff01;&#xff01;&#xff08;暨全额奖学金政策&#xff09; “面向未来改变游戏规则的——可持续能源与环境学域” &#xfffd;&#xfffd;&#xfffd;专注于能源环…...

uni-app:多种方法写入图片路径

一、文件在前端文件夹中 1、相对路径引用 从当前文件所在位置开始寻找图片文件的路径。../../ 表示返回两级目录&#xff0c;即从当前文件所在的 wind.vue 所在的位置开始向上回退两级。接着&#xff0c;进入 static 目录&#xff0c;再进入 look 目录&#xff0c;最后定位到 …...

共谋工业3D视觉发展,深眸科技以自研解决方案拓宽场景应用边界

随着中国工业领域自动化程度逐渐攀升&#xff0c;“机器换人”这一需求进一步提升。在传统2D工业视觉易受环境光干扰、无法进一步获取物体深度信息的限制条件下&#xff0c;工业3D视觉凭借着更强的空间和深度感知能力&#xff0c;以及通过点云数据获取物体距离和三维坐标信息的…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...