跳到主要内容博客系统 GitHub 第三方登录集成教程 | 极客日志Java大前端java
博客系统 GitHub 第三方登录集成教程
介绍如何在博客系统中集成 GitHub 第三方登录功能。步骤包括创建 GitHub OAuth App 获取凭证,配置后端环境变量与回调地址,以及前端路由与 API 调用实现。核心逻辑采用策略模式处理登录流程,涵盖 Token 交换、用户信息获取及 Sa-Token 登录验证。最后提供常见问题排查指南,确保回调地址一致性与本地测试连通性。
神经兮兮26K 浏览 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 | 你的网站首页地址 | https://your-domain.com |
| Authorization callback URL | 回调地址,非常重要 | https://your-domain.com/oauth/login/github |
⚠️ 重要提示:
- Authorization callback URL 必须填写:
https://你的域名/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 创建),添加:
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://your-domain.com/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://your-domain.com/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:
export default {
GITHUB_APP_ID: "你的 Client_ID",
GITHUB_REDIRECT_URL: "https://your-domain.com/oauth/login/github",
};
export default {
GITHUB_APP_ID: "123456789",
GITHUB_REDIRECT_URL: "https://your-domain.com/oauth/login/github",
};
步骤 2:本地测试配置(可选)
VITE_OAUTH_REDIRECT_BASE=https://abc123.ngrok-free.app
代码实现详解
1. 前端登录按钮
文件: src/components/Dialog/Login.vue
<svg-icon icon-class="github" size="2rem" v-if="showLogin('github')" @click="githubLogin"></svg-icon>
const githubLogin = () => {
user.savePath(route.path);
app.setLoginFlag(false);
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 ID
redirect_uri:回调地址
scope=user:请求用户信息权限
2. GitHub 授权回调
用户授权后,GitHub 会跳转回你的网站,URL 类似:
https://your-domain.com/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);
}
});
const handleOauthCallback = async (loginFn: Function) => {
try {
const { data } = await loginFn({ code: route.query.code as string });
if (data.flag) {
setToken(data.data);
await user.GetUserInfo();
if (user.email === "") {
window.$message?.warning("请绑定邮箱以便及时收到回复");
} else {
window.$message?.success("登录成功");
}
} else {
window.$message?.error("登录失败");
}
} catch {
window.$message?.error("登录失败,请重试");
}
const loginUrl = user.path;
router.push(loginUrl && loginUrl !== "" ? loginUrl : "/");
};
- 组件挂载时,从 URL 获取
code 参数
- 调用
githubLogin API,将 code 发送给后端
- 后端返回 Token,前端保存
- 获取用户信息
- 检查邮箱(GitHub 可能不返回邮箱,需要用户补充)
- 跳转回原页面
4. 前端 API 调用
文件: src/api/login/index.ts
export function githubLogin(data: GitInfo): AxiosPromise<Result<string>> {
return request({
url: "/oauth/github",
method: "post",
data,
});
}
类型定义: src/api/login/types.ts
export interface GitInfo {
code: string;
}
5. 后端 Controller
文件: src/main/java/com/ican/controller/LoginController.java
@PostMapping("/oauth/github")
public Result<String> githubLogin(@RequestBody CodeReq data) {
return Result.success(loginService.githubLogin(data));
}
请求 DTO: src/main/java/com/ican/model/vo/request/CodeReq.java
public class CodeReq {
private String code;
}
6. 后端 Service
文件: src/main/java/com/ican/service/LoginService.java
@Transactional(rollbackFor = Exception.class)
public String githubLogin(CodeReq data) {
return socialLoginStrategyContext.executeLoginStrategy(data, LoginTypeEnum.GITHUB);
}
7. 策略模式实现
系统使用策略模式处理不同平台的登录,GitHub 登录策略:
文件: src/main/java/com/ican/strategy/impl/GithubLoginStrategyImpl.java
@Service("githubLoginStrategyImpl")
public class GithubLoginStrategyImpl extends AbstractLoginStrategyImpl {
@Autowired
private GithubProperties githubProperties;
@Autowired
private RestTemplate restTemplate;
@Override
public SocialTokenDTO getSocialToken(CodeReq codeReq) {
TokenDTO githubToken = getGithubToken(codeReq.getCode());
return SocialTokenDTO.builder()
.accessToken(githubToken.getAccess_token())
.loginType(LoginTypeEnum.GITHUB.getLoginType())
.build();
}
@Override
public SocialUserInfoDTO getSocialUserInfo(SocialTokenDTO socialToken) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + socialToken.getAccessToken());
HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(null, headers);
GitUserInfoDTO gitUserInfoDTO = restTemplate.exchange(
githubProperties.getUserInfoUrl(),
HttpMethod.GET,
requestEntity,
GitUserInfoDTO.class
).getBody();
return SocialUserInfoDTO.builder()
.avatar(gitUserInfoDTO.getAvatar_url())
.id(gitUserInfoDTO.getId())
.nickname(gitUserInfoDTO.getLogin())
.build();
}
private TokenDTO getGithubToken(String code) {
MultiValueMap<String, String> githubData = new LinkedMultiValueMap<>();
githubData.add("client_id", githubProperties.getClientId());
githubData.add("client_secret", githubProperties.getClientSecret());
githubData.add("redirect_uri", githubProperties.getRedirectUrl());
githubData.add("code", code);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(githubData, headers);
try {
return restTemplate.exchange(
githubProperties.getAccessTokenUrl(),
HttpMethod.POST,
requestEntity,
TokenDTO.class
).getBody();
} catch (Exception e) {
throw new ServiceException("Github 登录错误");
}
}
}
8. 抽象登录模板
文件: src/main/java/com/ican/strategy/impl/AbstractLoginStrategyImpl.java
@Override
public String login(CodeReq data) {
User user;
SocialTokenDTO socialToken = getSocialToken(data);
SocialUserInfoDTO socialUserInfoDTO = getSocialUserInfo(socialToken);
User existUser = userMapper.selectOne(new LambdaQueryWrapper<User>()
.eq(User::getUsername, socialUserInfoDTO.getId())
.eq(User::getLoginType, socialToken.getLoginType()));
if (Objects.isNull(existUser)) {
user = saveLoginUser(socialToken, socialUserInfoDTO);
} else {
user = existUser;
}
StpUtil.checkDisable(user.getId());
StpUtil.login(user.getId());
return StpUtil.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. 登录后跳转错误
解决: 检查 githubLogin 函数中的 user.savePath(route.path) 是否正确执行
总结
用户点击 GitHub 登录
↓
跳转到 GitHub 授权页面
↓
用户授权,GitHub 回调到 /oauth/login/github?code=xxx
↓
前端发送 code 到后端 POST /oauth/github
↓
后端用 code 换 access_token
↓
后端用 access_token 获取用户信息
↓
查找或创建用户,Sa-Token 登录
↓
返回 Token 给前端
↓
前端保存 Token,获取用户信息,跳转回原页面
- ✅ 三处回调地址必须完全一致
- ✅ Client ID 和 Secret 配置正确
- ✅ 本地测试需要使用内网穿透
- ✅ 代码已经实现,只需配置即可使用
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online