项目场景:

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


1.配置gitee第三方设置

1.找到账号设置
【vue+nestjs】gitee第三方授权登录【超详细】-LMLPHP
2.找到数据管理下的第三方应用
【vue+nestjs】gitee第三方授权登录【超详细】-LMLPHP
3.点击创建,进入配置
【vue+nestjs】gitee第三方授权登录【超详细】-LMLPHP
【vue+nestjs】gitee第三方授权登录【超详细】-LMLPHP

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

10-18 23:19