当前位置: 首页 > news >正文

[SpringStack] 快速登录-9分钟给你站点接入Github登录

本文章案例为Java在web端接入GitHub登录,大致流程相同。

一: 设置Github的ClientId和

  • Settings --> DeveloperSettings -->OAuth Apps

1.1 创建一个newOAuth app

在这里插入图片描述

1.2 创建成功之后会生成一个Clinet ID和 Client secrets 用于在服务端交互时候使用

在这里插入图片描述

二:客户端按钮跳转代码

按钮的跳转地址为:

https://github.com/login/oauth/authorize?client_id=KaTeX parse error: Expected 'EOF', got '&' at position 16: {你生成的client_id}&̲redirect_uri={你服务端的跳转地址}.

假如我的client_id为 Ov22342345234,服务端的回调地址:http://127.0.0.1:8080/admin/github/callback

则我客户端的地址为:https://github.com/login/oauth/authorize?client_id=Ov22342345234&redirect_uri=http://127.0.0.1:8080/admin/github/callback

然后嵌入到web页面中。

<div class="row"><div class="col-xs-12"><a href="https://github.com/login/oauth/authorize?client_id=${你生成的client_id}&redirect_uri=http://127.0.0.1:8080/admin/github/callback" class="btn btn-default btn-block btn-flat">使用 GitHub 登录</a></div>
</div>

在这里插入图片描述

三:服务端回调地址:

用户在客户端点击GitHub登录点击授权登录,GitHub会回调到redirect_uri的地址,在后面会带一个code码,我们服务端回拿着这个code码换取access_token,因为要校验client_id下服务的唯一性

在这里插入图片描述

3.1 表设计:

如果B2C业务模式的话:C端用户player,B端用户 user
如果B2B2C业务模式的话: C端用户player,B端用户 user,多一个M端用户manager(用来控制平台的运转比如数据修复等等相关业务)

more字段是存储三方回调成功之后的用户信息,比如:{“login”:“xxx”,“id”:xxx,“avatar_url”:“xxx”,“name”:“xxx”,“email”:“xxxx@email.com”}

CREATE TABLE `third_user_account` (`third_user_account_id` bigint(20) unsigned NOT NULL COMMENT '主键ID',`create_id` bigint(20) NOT NULL COMMENT '创建人 @link user.id (-1为:系统)',`create_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',`modifier_id` bigint(20) unsigned DEFAULT NULL COMMENT '修改人id @link user.id (-1为:系统)',`modify_time` datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '修改时间',`version` int(11) NOT NULL DEFAULT '1' COMMENT '版本号',`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除: true 删除 false 未删除',`enabled` tinyint(1) DEFAULT '1' COMMENT '启用状态: true 启用 (默认)  false: 禁用',`is_bound` tinyint(1) DEFAULT '0' COMMENT '是否已绑定: 0 未绑定(默认) 1 已绑定 ',`third_plat_type_code` enum('github','qq','wechat') NOT NULL COMMENT '三方平台类型',`third_unique` varchar(100) NOT NULL COMMENT '三方平台唯一标识(如三方ID标识)',`third_username` varchar(155) DEFAULT NULL COMMENT '账号',`third_email` varchar(155) DEFAULT NULL COMMENT '邮箱',`more` text DEFAULT NULL COMMENT '其他',`remark` varchar(255) DEFAULT NULL COMMENT '备注',PRIMARY KEY (`third_user_account_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='三方用户账号表';

四: 编写服务端代码 (本文以Java为例)

这里的代码是GitHub

@RequestMapping("/github/callback")
public String handleGitHubCallback(@RequestParam("code") String code, HttpServletResponse response) {String accessToken = getAccessTokenFromGitHub(code);// 使用 access_token 获取用户信息GitHubUser user = getGitHubUserInfo(accessToken);// 绑定用户XxlJobUser jobUser = bindGitHubUserToPlatform(user);if (!validUserLogin(jobUser)) {log.error("用户:{}, 账号不存在或已经禁用", jobUser);return "账号不存在或已经禁用";}log.info("callback code:{}, state:{}", jobUser);CookieUtil.set(response, LOGIN_IDENTITY_KEY, makeToken(jobUser), Boolean.TRUE);// 重定向到用户登录后的页面return "redirect:/";
}
  • 使用 OkHttp 获取 GitHub access_token
private String getAccessTokenFromGitHub(String code) {String clientId = "你生成的client_id";String clientSecret = "你的密钥";String url = "https://github.com/login/oauth/access_token";String redirectUri = "http://127.0.0.1:8080/admin/github/callback";OkHttpClient client = new OkHttpClient();// 构建请求体RequestBody formBody = new FormBody.Builder().add("client_id", clientId).add("client_secret", clientSecret).add("code", code).add("redirect_uri", redirectUri).build();// 创建 POST 请求Request request = new Request.Builder().url(url).post(formBody).header("Accept", "application/json").build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) {throw new IOException("Unexpected code " + response);}// 获取响应体并返回 access_tokenString responseBody = response.body().string();return parseAccessTokenWithGson(responseBody);} catch (IOException e) {e.printStackTrace();}return null;
}
  • 使用 Gson 解析 access_token
private String parseAccessTokenWithGson(String responseBody) {// 使用 Gson 解析返回的 JSON 响应JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();return jsonObject.get("access_token").getAsString();
}
  • 根据 GitHub 用户信息绑定或创建用户账户.检查用户 email 是否已经注册,或者根据 GitHub id 进行绑定.
/*** 根据 GitHub 用户信息绑定或创建用户账户.* 检查用户 email 是否已经注册,或者根据 GitHub id 进行绑定.* @param gitHubUser* @return
*/
public XxlJobUser bindGitHubUserToPlatform(GitHubUser gitHubUser) {List<ThirdUserAccountPO> list = ChainWrappers.lambdaQueryChain(thirdUserAccountDAO).eq(ThirdUserAccountPO::getThirdUnique, gitHubUser.getId()).eq(ThirdUserAccountPO::getThirdPlatTypeCode, ThirdPlatformTypeEnum.GITHUB.getCode()).list();ThirdUserAccountPO thirdUserAccountPO;if (CollectionUtils.isEmpty(list)) {thirdUserAccountPO = new ThirdUserAccountPO();thirdUserAccountPO.setThirdUnique(String.valueOf(gitHubUser.getId()));thirdUserAccountPO.setCreateId(-1L);thirdUserAccountPO.setThirdPlatTypeCode(ThirdPlatformTypeEnum.GITHUB.getCode());Optional.ofNullable(gitHubUser.getEmail()).ifPresent(v -> thirdUserAccountPO.setThirdEmail(v));Optional.ofNullable(gitHubUser.getLogin()).ifPresent(v -> thirdUserAccountPO.setThirdUsername(v));thirdUserAccountPO.setMore(new Gson().toJson(gitHubUser));thirdUserAccountPO.setIsBound(Boolean.TRUE);thirdUserAccountDAO.insert(thirdUserAccountPO);} else {thirdUserAccountPO = list.get(0);}//生成绑定到后台账户XxlJobUser xxlJobUser = ChainWrappers.lambdaQueryChain(xxlJobUserDao).eq(XxlJobUser::getThirdUserAccountId, thirdUserAccountPO.getThirdUserAccountId()).one();String thirdUnique = thirdUserAccountPO.getThirdUnique();if (xxlJobUser == null) {xxlJobUser = new XxlJobUser();xxlJobUser.setUsername("gh_".concat(thirdUnique.substring(0,3)).concat(thirdUserAccountPO.getThirdUsername()));HashCode hashPwd = Hashing.hmacMd5(thirdUnique.getBytes(StandardCharsets.UTF_8)).hashString(thirdUnique, StandardCharsets.UTF_8);xxlJobUser.setPassword(hashPwd.toString());xxlJobUser.setRole(0);xxlJobUser.setThirdUserAccountId(thirdUserAccountPO.getThirdUserAccountId());xxlJobUserDao.save(xxlJobUser);}return xxlJobUser;
}
  • 校验用户是否是可用状态
private Boolean validUserLogin(XxlJobUser xxlJobUser) {if (xxlJobUser.getDeleted() || xxlJobUser.getStatus() != AccountStatusEnum.ENABLED.getCode()) {return Boolean.FALSE;}return Boolean.TRUE;
}

总结

本文只是使用web演示了GitHub的登录接入,如果使用App跳转,只需要把接口请求成功后,返回跳转地址的标识改为跳转回APP就可以了。

参考资料 & 致谢

[1] GitHub Apps
[2] About creating GitHub Apps


http://www.mrgr.cn/news/65146.html

相关文章:

  • RabbitMQ交换机类型
  • 针对解决前后端BUG的个人笔记
  • python项目实战 小说下载源码
  • Redis常见面试题概览——针对实习面试
  • 智慧汇聚:十款企业培训工具打造学习型企业
  • Selenium的下载及chrome环境搭建
  • 华为OD机试 - 第 K 个字母在原来字符串的索引(Java 2024 E卷 100分)
  • grpc 云原生 概念介绍
  • 2024 CSS保姆级教程 - BFC详解
  • PostgreSQL 安装 POSTGRES_FDW
  • pcdn的成本构成(壹)
  • CentOS 7 安装 ntp,自动校准系统时间
  • Python编程风格:使用语义更加明确的方法
  • 数据库基础(1) . 关系型数据库
  • 在 Vision Pro 上打造成功的沉浸式叙述应用:探索极致交互体验
  • VidPanos:从随手拍摄的平移视频生成全景视频
  • mysql报错:Field id doesnt hava a default value
  • 《LoRA-IR》:2024年10月中科院自动所提出了一种用于多种修复图像恶化退化问题的LORA,效果拔群
  • 计算机毕业设计Spark+大模型股票推荐系统 股票预测系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI
  • Node.js:ES6 模块化 Promise
  • Intel nuc x15 重装系统步骤和注意事项(LAPKC71F、LAPKC71E、LAPKC51E)
  • XPath 实例
  • 哪些因素导致了 MySQL 数据库的延时呢?
  • Vuex的基本使用
  • Nginx 在中小企业的初级应用实操指南
  • C语言 | Leetcode 题解之第535题TinyURL的加密与解密