GitHub,Gitee,qq 第三方登录配置完整教程
GitHub 第三方登录配置完整教程
本教程将详细介绍如何在博客系统中集成 GitHub 第三方登录功能,包括 GitHub OAuth App 创建、前后端配置、代码实现等,适合零基础小白学习。
📚 目录
什么是 GitHub 第三方登录
GitHub 第三方登录(OAuth 2.0)允许用户使用 GitHub 账号登录你的网站,无需注册新账号。用户点击"GitHub 登录"后,会跳转到 GitHub 授权页面,授权后 GitHub 会回调到你的网站,完成登录。
优势:
- ✅ 用户无需注册,一键登录
- ✅ 安全可靠,由 GitHub 管理用户认证
- ✅ 自动获取用户头像、昵称等信息
创建 GitHub OAuth App
步骤 1:登录 GitHub
访问 GitHub.com,使用你的账号登录(如果没有账号,先注册一个)。
步骤 2:进入开发者设置
- 点击右上角头像
- 点击 Settings(设置)
- 左侧菜单滚动到最下面,找到 Developer settings(开发者设置)
- 点击进入
步骤 3:创建 OAuth App
- 在左侧菜单点击 OAuth Apps(OAuth 应用)
- 点击右上角 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");};流程说明:
- 用户点击 GitHub 图标
- 保存当前页面路径(登录后跳转回来)
- 关闭登录弹窗
- 跳转到 GitHub 授权页面,URL 包含:
client_id:你的 GitHub Client IDredirect_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 :"/");};流程说明:
- 组件挂载时,从 URL 获取
code参数 - 调用
githubLoginAPI,将code发送给后端 - 后端返回 Token,前端保存
- 获取用户信息
- 检查邮箱(GitHub 可能不返回邮箱,需要用户补充)
- 跳转回原页面
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();}完整流程:
- 用
code换取access_token - 用
access_token获取用户信息(头像、ID、用户名) - 查找数据库中是否存在该用户(通过 GitHub ID 和登录类型)
- 如果不存在,创建新用户并分配普通用户角色
- 检查账号是否被封禁
- 使用 Sa-Token 登录,返回 Token 给前端
测试登录
1. 确保配置正确
检查三处地址是否完全一致:
- ✅ GitHub OAuth App 的回调地址
- ✅ 前端
config.ts的GITHUB_REDIRECT_URL - ✅ 后端
.env或application-dev.yml的redirect-url
2. 启动服务
# 启动后端cd blog-springboot mvn spring-boot:run # 启动前端cd blog-vue/shoka-blog npm run dev 3. 测试登录
- 访问网站首页
- 点击右上角"登录"
- 点击 GitHub 图标
- 跳转到 GitHub 授权页面
- 点击 Authorize(授权)
- 自动跳转回网站,完成登录
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,获取用户信息,跳转回原页面 关键点:
- ✅ 三处回调地址必须完全一致
- ✅ Client ID 和 Secret 配置正确
- ✅ 本地测试需要使用内网穿透
- ✅ 代码已经实现,只需配置即可使用
祝你配置顺利! 🎉