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

news/2024/5/17 20:09:09 标签: vue.js, gitee, 前端

项目场景:

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


gitee_5">1.配置gitee第三方设置

1.找到账号设置
在这里插入图片描述
2.找到数据管理下的第三方应用
在这里插入图片描述
3.点击创建,进入配置
在这里插入图片描述
在这里插入图片描述

2.代码演示

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

代码演示

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

  1. 前端点击gitee图标登录代码:
<div @click="handleToLogin('gitee')">
     gitee
</div>

const handleToLogin = (type:string)=>{
   window.location.href="http://localhost:3000/user/oauth/gitee"
}
  1. http://localhost:3000/user/oauth/gitee后端接口代码
	@Get('/oauth/gitee')
  async gitee(@Res() response: Response) {
    let cid = data.cid;
    let redirectUrl = data.redirectUrl;//回调路劲获取code
    //通过该路劲获取code,这里的回调地址就是你的前端地址
    response.redirect(`https://gitee.com/oauth/authorize?client_id=${cid}&redirect_uri=${redirectUrl}&response_type=code`)
  }
  1. 回调地址前端代码
<template>
    <div class="u-f u-f-ac u-f-ajc" style="width: 100%;height:100vh">
        <template v-if="isOauth">
            <el-result
                    icon="success"
                    title="授权成功,跳转中..."
            >
            </el-result>
        </template>
        <template v-else>
            <el-result
                    icon="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对后端发起请求,获取gitee用户信息
        let {code} = query;
        let form = {
            code
        }
        requestGiteeLogin(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. requestGiteeLogin请求的后端代码
//gitee登录
  @Post('/oauth/giteeLogin')
  giteeLogin(@Body() giteeLoginDto:GiteeLoginDto,@IpAddress() clientIp: string) {
     let {code,operationSystem,browser} = giteeLoginDto
     //获取accessToken
    let accessToken = await this.handleGetGiteeAccessToken(code)
    if(!accessToken.data){
      return this.msgService.fail("code过期,请重新登录")
    }
    //使用accessToken获取gitee用户信息
    let giteeInfo:any = await this.getGiteeInfoByAccessToken(accessToken.data);
    if(!giteeInfo.data){
      return this.msgService.fail("获取gitee账号信息失败")
    }
    let { id, name, avatar_url, email } = giteeInfo.data;
    let giteeId = sysConfigEnum.giteeLoginConfig + JSON.parse(JSON.stringify(id));
    //判断gitee是否有关联账号。如果有就登陆,没有就新创建一个账号
    let userNum = await this.userEntity.createQueryBuilder().where({ giteeId:giteeId }).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,giteeId:giteeId,roleId:roleData.id}).execute();
      }catch (error) {
        throw new HttpException(error,HttpStatus.SERVICE_UNAVAILABLE)
      }
      id = userData.identifiers[0]["id"]
    }else{
      let userData = await this.userEntity.createQueryBuilder().where({giteeId:giteeId}).getOne()
      username = userData.username
      id = userData.id;
    }
    let ip  = handleDealIpv6ToIpv4(clientIp)
    let token = this.authService.createToken({id,username,ip})
    await this.updateUserInfoStatus(id,token,ip,operationSystem,browser)
    return {
      id,username,token
    }
  }
  
//随机生成账号
  async handleGetUsername (username){
    const num = await this.userEntity.createQueryBuilder().where({username}).getCount()
    if(num>0){
      username = handleGetCode(8);
     return this.handleGetUsername(username)
    }
    return username;
  }

  //获取gitee的accessToken
  async handleGetGiteeAccessToken(code:string):Promise<resInterface>{
    let key = sysConfigEnum.giteeLoginConfig
    let data = await this.sysConfigService.handleGetSysData(key)
    if(!data.cid || !data.secret || !data.redirectUrl){
      return {data:false,msg:""};
    }
    let cid = data.cid;
    let redirectUrl = data.redirectUrl;//回调路劲获取code
    let secret = data.secret;//回调路劲获取code
    let authData = await axios.post(giteeOauthConfig.authURL,{
      code,
      client_id: cid,
      redirect_uri: redirectUrl,
      client_secret: secret,
    }).then(res=>{
      return res.data;
    }).catch(err=>{
      return err.data
    })
    if(authData?.error){
      return this.msgService.commonRes(false,authData?.error?.error_description);
    }else{
      return this.msgService.commonRes(authData?.access_token,"");
    }
  }
  //通过access_token获取gitee信息
  async getGiteeInfoByAccessToken(accessToken: boolean | string){
    let authData = await axios.get(giteeOauthConfig.giteeUserAPI+`?access_token=${accessToken}`).then(res=>{
      return res.data;
    }).catch(err=>{
      return err.data
    })
    if(authData?.error){
      return this.msgService.commonRes(false,authData?.error?.error_description);
    }else{
      return this.msgService.commonRes(authData,"");
    }
  }

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}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

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


http://www.niftyadmin.cn/n/5099934.html

相关文章

【Arduino TFT】 记录使用DMA优化TFT屏帧率

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-10-18 ❤️❤️ 本篇更新记录 2023-10-18 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

交通目标检测-行人车辆检测流量计数 - 计算机竞赛

文章目录 0 前言1\. 目标检测概况1.1 什么是目标检测&#xff1f;1.2 发展阶段 2\. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…

世界新冠疫情大数据案例

一、环境要求 HadoopHiveSparkHBase 开发环境。 二、数据描述 countrydata.csv 是世界新冠疫情数&#xff0c;数据中记录了从疫情开始至 7 月 2 日&#xff0c;以国家为单位的每日新冠疫情感染人数的数据统计。字段说明如下&#xff1a; 世界新冠疫情数据 countrydata.cs…

selenium多窗口、多iframe切换、等待、

1、多标签/多窗口之间的切换 场景&#xff1a; 在页面操作过程中有时候点击某个链接会弹出新的窗口&#xff0c;这时就需要切换到新打开的窗口上进行操作。这种情况下&#xff0c;需要识别多标签或窗口的情况。 操作方法&#xff1a; switch_to.window()方法&#xff1a;切换…

微信小程序4

一自定义组件应用 1.介绍 微信小程序自定义组件是指开发者可以自定义组件&#xff0c;将一些常用的 UI 元素封装成一个自定义组件&#xff0c;然后在多个页面中复用该组件&#xff0c;实现代码复用和页面性能优化的效果。 2.自定义组件分为两种类型 组件模板类型&#xff1a;…

百度最强大模型发布,百度网盘和文库的实测体验

&#x1f341; 展望&#xff1a;若本篇讲解内容帮助到您&#xff0c;请帮忙点个赞吧, 您的支持是我继续写作的最大动力. 关注我, 带您了解更多 AI 资讯和 AI 小技巧. 引言 2023年百度世界大会在10月17日的春光中于北京的首钢园精彩召开。这次大会的核心主题——“生成未来 PRO…

如何实现线程安全?

简单描述一下线程安全问题&#xff1a;在程序并发执行的过程中&#xff0c;对于临界区的一些共享数据&#xff0c;可能同时会有多个线程对其进行修改&#xff0c;造成数据覆盖、脏读等一系列问题 如何实现线程安全&#xff1f; 首先想到的就是实现线程同步&#xff0c;让并发…

荣耀推送服务业务介绍

概述 荣耀推送服务&#xff08;HONOR Push&#xff09;是荣耀公司向开发者提供的消息推送服务&#xff0c;通过服务端与客户端建立一条稳定、可靠的长连接通道&#xff0c;向荣耀手机系统上的APP应用客户端实时推送消息的服务。无论应用进程是否存在&#xff0c;均可正常收到消…