GitHub,Gitee,qq 第三方登录配置完整教程

GitHub,Gitee,qq 第三方登录配置完整教程

GitHub 第三方登录配置完整教程

本教程将详细介绍如何在博客系统中集成 GitHub 第三方登录功能,包括 GitHub OAuth App 创建、前后端配置、代码实现等,适合零基础小白学习。

📚 目录

  1. 什么是 GitHub 第三方登录
  2. 创建 GitHub OAuth App
  3. 后端配置
  4. 前端配置
  5. 代码实现详解
  6. 测试登录
  7. 常见问题

什么是 GitHub 第三方登录

GitHub 第三方登录(OAuth 2.0)允许用户使用 GitHub 账号登录你的网站,无需注册新账号。用户点击"GitHub 登录"后,会跳转到 GitHub 授权页面,授权后 GitHub 会回调到你的网站,完成登录。

优势:

  • ✅ 用户无需注册,一键登录
  • ✅ 安全可靠,由 GitHub 管理用户认证
  • ✅ 自动获取用户头像、昵称等信息

创建 GitHub OAuth App

步骤 1:登录 GitHub

访问 GitHub.com,使用你的账号登录(如果没有账号,先注册一个)。

步骤 2:进入开发者设置

  1. 点击右上角头像
  2. 点击 Settings(设置)
  3. 左侧菜单滚动到最下面,找到 Developer settings(开发者设置)
  4. 点击进入

步骤 3:创建 OAuth App

  1. 在左侧菜单点击 OAuth Apps(OAuth 应用)
  2. 点击右上角 New OAuth App(新建 OAuth 应用)

步骤 4:填写应用信息

填写以下信息:

字段说明示例
Application name应用名称,会显示给用户我的博客
Homepage URL你的网站首页地址http://ariconline.top
Authorization callback URL回调地址,非常重要http://ariconline.top/oauth/login/github

⚠️ 重要提示:

  • Authorization callback URL 必须填写:http://你的域名/oauth/login/github
  • 这个地址必须和前后端配置的地址完全一致(包括协议 http/https)
  • 本地测试需要使用内网穿透工具(如 ngrok),详见本地测试指南

步骤 5:注册应用

点击 Register application(注册应用)

步骤 6:获取 Client ID 和 Secret

注册成功后,你会看到:

  • Client ID:类似 1decdeff65c4ca8daa07(公开的,可以暴露)
  • Client secrets:点击 Generate a new client secret 生成(只显示一次,务必保存

⚠️ 重要: Client Secret 生成后只显示一次,请立即复制保存。如果丢失,需要重新生成。


后端配置

步骤 1:配置环境变量

blog-springboot 目录下找到 .env 文件(如果没有,复制 .env.example 创建),添加:

# GitHub OAuth 配置OAUTH_GITHUB_CLIENT_ID=你的Client_ID OAUTH_GITHUB_CLIENT_SECRET=你的Client_Secret 

示例:

OAUTH_GITHUB_CLIENT_ID=1decdeff65c4ca8daa07 OAUTH_GITHUB_CLIENT_SECRET=abc123def456ghi789jkl012mno345pqr678stu901 

步骤 2:配置回调地址(可选)

编辑 src/main/resources/application-dev.yml

oauth:github:client-id: ${OAUTH_GITHUB_CLIENT_ID:}client-secret: ${OAUTH_GITHUB_CLIENT_SECRET:}redirect-url: ${OAUTH_GITHUB_REDIRECT:http://ariconline.top/oauth/login/github}access-token-url: https://github.com/login/oauth/access_token user-info-url: https://api.github.com/user 

说明:

  • redirect-url 是回调地址,默认使用环境变量 OAUTH_GITHUB_REDIRECT
  • 如果环境变量未设置,使用默认值 http://ariconline.top/oauth/login/github
  • 本地测试时,可以在 .env 中设置 OAUTH_GITHUB_REDIRECT=https://你的ngrok地址/oauth/login/github

步骤 3:重启后端服务

修改配置后,重启 Spring Boot 后端服务使配置生效。


前端配置

步骤 1:修改配置文件

编辑 blog-vue/shoka-blog/src/assets/js/config.ts

exportdefault{// GitHub 的 Client ID(从 GitHub OAuth App 页面获取)GITHUB_APP_ID:"你的Client_ID",// GitHub 回调地址(必须与 GitHub OAuth App 中填写的完全一致)GITHUB_REDIRECT_URL:"http://ariconline.top/oauth/login/github",// ... 其他配置};

示例:

exportdefault{GITHUB_APP_ID:"123456789",GITHUB_REDIRECT_URL:"http://ariconline.top/oauth/login/github",};

步骤 2:本地测试配置(可选)

如果要在本地测试,编辑 .env.dev

# 使用内网穿透地址(如 ngrok)VITE_OAUTH_REDIRECT_BASE=https://abc123.ngrok-free.app 

然后 config.ts 会自动使用这个地址。


代码实现详解

1. 前端登录按钮

在登录弹窗中,添加 GitHub 登录按钮:

文件:src/components/Dialog/Login.vue

<svg-icon icon-class="github" size="2rem" v-if="showLogin('github')" @click="githubLogin" ></svg-icon> 

点击事件:

constgithubLogin=()=>{// 保存当前路径,登录后跳转回来 user.savePath(route.path);// 关闭登录弹窗 app.setLoginFlag(false);// 跳转到 GitHub 授权页面 window.open("https://github.com/login/oauth/authorize?client_id="+ config.GITHUB_APP_ID+"&redirect_uri="+ config.GITHUB_REDIRECT_URL+"&scope=user","_self");};

流程说明:

  1. 用户点击 GitHub 图标
  2. 保存当前页面路径(登录后跳转回来)
  3. 关闭登录弹窗
  4. 跳转到 GitHub 授权页面,URL 包含:
    • client_id:你的 GitHub Client ID
    • redirect_uri:回调地址
    • scope=user:请求用户信息权限

2. GitHub 授权回调

用户授权后,GitHub 会跳转回你的网站,URL 类似:

http://ariconline.top/oauth/login/github?code=abc123def456... 

路由配置:src/router/routes/index.ts

{ path:"/oauth/login/github",component:()=>import("@/components/Oauth/index.vue"),}

3. 回调处理组件

文件:src/components/Oauth/index.vue

onMounted(()=>{const path = route.path;if(path ==="/oauth/login/github"){handleOauthCallback(githubLogin);}// ...});consthandleOauthCallback=async(loginFn:Function)=>{try{// 1. 从 URL 中获取 codeconst{ data }=awaitloginFn({ code: route.query.code asstring});if(data.flag){// 2. 保存 TokensetToken(data.data);// 3. 获取用户信息await user.GetUserInfo();// 4. 检查邮箱(GitHub 可能不返回邮箱)if(user.email ===""){ window.$message?.warning("请绑定邮箱以便及时收到回复");}else{ window.$message?.success("登录成功");}}else{ window.$message?.error("登录失败");}}catch{ window.$message?.error("登录失败,请重试");}// 5. 跳转回原页面或首页const loginUrl = user.path; router.push(loginUrl && loginUrl !==""? loginUrl :"/");};

流程说明:

  1. 组件挂载时,从 URL 获取 code 参数
  2. 调用 githubLogin API,将 code 发送给后端
  3. 后端返回 Token,前端保存
  4. 获取用户信息
  5. 检查邮箱(GitHub 可能不返回邮箱,需要用户补充)
  6. 跳转回原页面

4. 前端 API 调用

文件:src/api/login/index.ts

/** * GitHub登录 * @param code 第三方code(从 GitHub 回调 URL 中获取) * @returns Token */exportfunctiongithubLogin(data: GitInfo): AxiosPromise<Result<string>>{returnrequest({ url:"/oauth/github", method:"post", data,});}

类型定义:src/api/login/types.ts

exportinterfaceGitInfo{ code:string;// GitHub 返回的授权码}

5. 后端 Controller

文件:src/main/java/com/ican/controller/LoginController.java

@PostMapping("/oauth/github")publicResult<String>githubLogin(@RequestBodyCodeReq data){returnResult.success(loginService.githubLogin(data));}

请求 DTO:src/main/java/com/ican/model/vo/request/CodeReq.java

publicclassCodeReq{privateString code;// GitHub 返回的授权码}

6. 后端 Service

文件:src/main/java/com/ican/service/LoginService.java

@Transactional(rollbackFor =Exception.class)publicStringgithubLogin(CodeReq data){// 调用策略模式处理 GitHub 登录return socialLoginStrategyContext.executeLoginStrategy(data,LoginTypeEnum.GITHUB);}

7. 策略模式实现

系统使用策略模式处理不同平台的登录,GitHub 登录策略:

文件:src/main/java/com/ican/strategy/impl/GithubLoginStrategyImpl.java

@Service("githubLoginStrategyImpl")publicclassGithubLoginStrategyImplextendsAbstractLoginStrategyImpl{@AutowiredprivateGithubProperties githubProperties;// 配置属性@AutowiredprivateRestTemplate restTemplate;// HTTP 请求工具/** * 第一步:用 code 换取 access_token */@OverridepublicSocialTokenDTOgetSocialToken(CodeReq codeReq){TokenDTO githubToken =getGithubToken(codeReq.getCode());returnSocialTokenDTO.builder().accessToken(githubToken.getAccess_token()).loginType(LoginTypeEnum.GITHUB.getLoginType()).build();}/** * 第二步:用 access_token 获取用户信息 */@OverridepublicSocialUserInfoDTOgetSocialUserInfo(SocialTokenDTO socialToken){// 设置请求头:Authorization: Bearer {access_token}HttpHeaders headers =newHttpHeaders(); headers.set("Authorization","Bearer "+ socialToken.getAccessToken());HttpEntity<Map<String,String>> requestEntity =newHttpEntity<>(null, headers);// 调用 GitHub API 获取用户信息GitUserInfoDTO gitUserInfoDTO = restTemplate.exchange( githubProperties.getUserInfoUrl(),// https://api.github.com/userHttpMethod.GET, requestEntity,GitUserInfoDTO.class).getBody();// 返回用户信息returnSocialUserInfoDTO.builder().avatar(gitUserInfoDTO.getAvatar_url())// 头像.id(gitUserInfoDTO.getId())// GitHub 用户 ID.nickname(gitUserInfoDTO.getLogin())// GitHub 用户名.build();}/** * 用 code 换取 access_token 的详细实现 */privateTokenDTOgetGithubToken(String code){// 构建请求参数MultiValueMap<String,String> githubData =newLinkedMultiValueMap<>(); githubData.add("client_id", githubProperties.getClientId()); githubData.add("client_secret", githubProperties.getClientSecret()); githubData.add("redirect_uri", githubProperties.getRedirectUrl()); githubData.add("code", code);// 设置请求头:Accept: application/jsonHttpHeaders headers =newHttpHeaders(); headers.setAccept(List.of(MediaType.APPLICATION_JSON));HttpEntity<MultiValueMap<String,String>> requestEntity =newHttpEntity<>(githubData, headers);try{// 发送 POST 请求到 GitHubreturn restTemplate.exchange( githubProperties.getAccessTokenUrl(),// https://github.com/login/oauth/access_tokenHttpMethod.POST, requestEntity,TokenDTO.class).getBody();}catch(Exception e){thrownewServiceException("Github登录错误");}}}

8. 抽象登录模板

文件:src/main/java/com/ican/strategy/impl/AbstractLoginStrategyImpl.java

@OverridepublicStringlogin(CodeReq data){User user;// 1. 获取 GitHub TokenSocialTokenDTO socialToken =getSocialToken(data);// 2. 获取 GitHub 用户信息SocialUserInfoDTO socialUserInfoDTO =getSocialUserInfo(socialToken);// 3. 查找用户是否已注册User existUser = userMapper.selectOne(newLambdaQueryWrapper<User>().eq(User::getUsername, socialUserInfoDTO.getId()).eq(User::getLoginType, socialToken.getLoginType()));// 4. 如果用户不存在,创建新用户if(Objects.isNull(existUser)){ user =saveLoginUser(socialToken, socialUserInfoDTO);}else{ user = existUser;}// 5. 检查账号是否被封禁StpUtil.checkDisable(user.getId());// 6. 使用 Sa-Token 登录,返回 TokenStpUtil.login(user.getId());returnStpUtil.getTokenValue();}

完整流程:

  1. code 换取 access_token
  2. access_token 获取用户信息(头像、ID、用户名)
  3. 查找数据库中是否存在该用户(通过 GitHub ID 和登录类型)
  4. 如果不存在,创建新用户并分配普通用户角色
  5. 检查账号是否被封禁
  6. 使用 Sa-Token 登录,返回 Token 给前端

测试登录

1. 确保配置正确

检查三处地址是否完全一致:

  • ✅ GitHub OAuth App 的回调地址
  • ✅ 前端 config.tsGITHUB_REDIRECT_URL
  • ✅ 后端 .envapplication-dev.ymlredirect-url

2. 启动服务

# 启动后端cd blog-springboot mvn spring-boot:run # 启动前端cd blog-vue/shoka-blog npm run dev 

3. 测试登录

  1. 访问网站首页
  2. 点击右上角"登录"
  3. 点击 GitHub 图标
  4. 跳转到 GitHub 授权页面
  5. 点击 Authorize(授权)
  6. 自动跳转回网站,完成登录

4. 验证登录

  • ✅ 右上角显示 GitHub 头像
  • ✅ 可以访问"我的代办"等登录用户功能
  • ✅ 个人中心显示 GitHub 信息

常见问题

1. 回调地址不匹配

错误信息:redirect_uri_mismatch

原因: 三处回调地址不一致

解决: 确保以下三处完全一致(包括协议 http/https):

  • GitHub OAuth App 设置
  • 前端 config.ts
  • 后端配置

2. Client Secret 错误

错误信息:bad_verification_code

原因: Client Secret 配置错误或已过期

解决:

  • 检查 .env 文件中的 OAUTH_GITHUB_CLIENT_SECRET 是否正确
  • 如果丢失,在 GitHub OAuth App 页面重新生成

3. 本地测试无法回调

原因: GitHub 无法访问 localhost

解决: 使用内网穿透工具(ngrok、natapp),详见本地测试指南

4. 用户没有邮箱

现象: 登录成功但提示"请绑定邮箱"

原因: GitHub 用户可能没有公开邮箱或未授权邮箱权限

解决:

  • 用户可以在个人中心补充邮箱
  • 或在 GitHub 设置中将邮箱设为公开

5. 登录后跳转错误

原因:user.path 保存的路径不正确

解决: 检查 githubLogin 函数中的 user.savePath(route.path) 是否正确执行


总结

GitHub 第三方登录的实现流程:

用户点击 GitHub 登录 ↓ 跳转到 GitHub 授权页面 ↓ 用户授权,GitHub 回调到 /oauth/login/github?code=xxx ↓ 前端发送 code 到后端 POST /oauth/github ↓ 后端用 code 换 access_token ↓ 后端用 access_token 获取用户信息 ↓ 查找或创建用户,Sa-Token 登录 ↓ 返回 Token 给前端 ↓ 前端保存 Token,获取用户信息,跳转回原页面 

关键点:

  1. ✅ 三处回调地址必须完全一致
  2. ✅ Client ID 和 Secret 配置正确
  3. ✅ 本地测试需要使用内网穿透
  4. ✅ 代码已经实现,只需配置即可使用

祝你配置顺利! 🎉

Read more

C++并集查找

C++并集查找

前言 C++图论 C++算法与数据结构 本博文代码打包下载 基本概念 并查集(Union-Find)是一种用于处理动态连通性(直接或间接相连)的数据结构,主要支持两种操作:union 和 find。通过这两个基本操作,可以高效地管理一组元素之间的连通关系。 Find: 查找节点所在有向树的根。 Union: 将两个不同的有向图合并为一棵树。 暴力做法 并集查找处理无向图的数据结构:有向森林,每棵树都是内向树。连通子图都直接或间接指向根,根出度为0,其它节点出度为1。vPar记录各节点的父节点。 Find(u)函数寻找u所在有向树的根(最远祖先): while(-1!= vPar[u]){ u =vPar}return u; 判断u和v是否连通: returnFind(u)==Find(v) 连通: root1 =Find(

By Ne0inhk
“深入浅出”系列之C++:100个C++开源项目

“深入浅出”系列之C++:100个C++开源项目

1.C++服务器 项目地址:https://github.com/yuesong-feng/30dayMakeCppServer 2.《btop》(命令行资源监视器) 项目地址:https://github.com/aristocratos/btop 3.C++轻量级WebServer服务器 项目地址:https://github.com/qinguoyi/TinyWebServer 4.剪贴板工具 项目地址:https://github.com/Slackadays/Clipboard 5.dbg 项目地址:https://github.com/sharkdp/dbg-macro 6.计算机操作系统 项目地址:https://github.com/SamyPesse/

By Ne0inhk

vs配置MySQL connector C++

参考文章:如有侵权,联系删帖! 1、版权声明:本文为ZEEKLOG博主「hbwhypw」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.ZEEKLOG.net/hbwhypw/article/details/148299750 2、版权声明:本文为ZEEKLOG博主「Eclips3」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接: https://blog.ZEEKLOG.net/weixin_44343938/article/details/141568106 具体操作在后面,这几个说明是为了给大家一些提示,小心有坑哦,我就是被这个坑恶心到了!所以有了此篇文章,这也是我第一次写博客,欢迎各位批评指正。 避坑说明:

By Ne0inhk
【C++:继承】C++面向对象继承全面解析:派生类构造、多继承、菱形虚拟继承与设计模式实践

【C++:继承】C++面向对象继承全面解析:派生类构造、多继承、菱形虚拟继承与设计模式实践

🔥艾莉丝努力练剑:个人主页 ❄专栏传送门:《C语言》、《数据结构与算法》、C/C++干货分享&学习过程记录、Linux操作系统编程详解、笔试/面试常见算法:从基础到进阶 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬艾莉丝的简介: 🎬艾莉丝的C++专栏简介: 目录 C++的两个参考文档 4  ~>  派生类的默认成员函数专题 4.4  实现一个不可继承类实现 4.4.1  间接实现:【C++98】构造函数私有的类不能被继承 4.4.2  直接实现:final关键字修改基类 4.4.3  代码实现 4.4.4  final关键字

By Ne0inhk