SpringBoot + Vue实现Github第三方登录

        前言:毕业设计终于好了,希望能有空多写几篇

1. 获取Github账号的Client ID和Client secrets

        首先点击这个链接进入Github的OAuth Apps页面,页面展示如下:

之后我们可以创建一个新的apps:

        填写资料:

创建之后就可以获取到Client ID 和 Client Scrects

2. github用户信息获取流程

        获取到Client ID 和 Client Scrects之后,就可以开始写代码了,这里先放上接口文档

2.1 获取授权码Authorize Code

请求路径:

GET https://github.com/login/oauth/authorize

主要携带参数:

参数名称类型描述
client_idstring必需带上,注册时从GitHub收到的客户端ID。
redirect_uristring应用程序中的URL,授权后用户将被发送到该URL。
scopestring用空格分隔的作用域列表。如果未提供,则范围默认为未为应用程序授权任何范围的用户的空列表。对于已授权应用程序范围的用户,不会向用户显示包含范围列表的OAuth授权页面。
statestring一个随机字符串,用于防止跨站点请求伪造攻击。
allow_signupstring在OAuth流程中,是否会向未经身份验证的用户提供注册GitHub的选项。默认为true。当策略禁止注册时使用false。

请求的响应结果:

        前面参数中的redirect_uri填写的返回路径,同时这个返回路径会携带code和state,基于此,我们可以在前端定义一个跳转到 Github 授权页面的链接:

<a href="https://github.com/login/oauth/authorize?scope=user:email&client_id=请填写自己的client_id">Github登录</a>

(ps:这里我使用了个图标,一样的)

点击之后就有了这个画面:

        输入正确的密码之后,GitHub将重定向回站点,并在代码参数中携带code以及在前一步中提供的状态参数state。临时代码将在10分钟后失效。如果状态不匹配,则是第三方创建了请求,开发者应该中止该过程。

我们就可以使用Vue中的route获取这个code参数,

这里我的router.js中配置了返回路径对应路由:

const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),export default routes: [{path: "/",name: "post",component: Post,},
]});

然后在页面中拿到这个code 

onMounted(async() => {let code = route.query.code;if(code === undefined || code === null || code === ""){message.error("登录失败:code为空");return;}//然后发送这个code给后端就行了,很简单,不多赘述
});
2.2 通过授权码获取access_token

请求URL:

POST https://github.com/login/oauth/access_token

携带参数: 

参数名称类型描述
client_idstring必需!前面的获取Client ID
client_secretstring必需!前面获取的Client Secret
codestring必需!上一步获取到的code

返回参数:

Accept: application/json
{"access_token":"gho_16C7e42F292c6912E7710c838347Ae178B4a","scope":"repo,gist","token_type":"bearer"
}

于是乎我们拿到了access_token

代码编写如下:

Map<String, Object> data = new HashMap<>();data.put("client_id", 你的client_id);data.put("client_secret", 你的client_secret);data.put("code", 收到的code);//        使用HttpUtil发送post请求String post = HttpRequest.post(accessTokenURL).header(Header.ACCEPT, "application/json").body(JSONUtil.toJsonStr(data)).execute().body();

然后再获取access-token:

String accessToken = null;try{JSONObject postResponse = JSONObject.parseObject(post);accessToken = postResponse.getString("access_token"); //获取密钥if(accessToken == null || accessToken.equals("")){throw new BusinessException(ErrorCode.LOGIN_ERROR);}}catch (Exception e){throw new BusinessException(ErrorCode.LOGIN_ERROR);}
2.3 根据access_token获取用户信息进行登录

请求地址:

Authorization: token ${access_token}
GET https://api.github.com/user

返回参数:

{"login": "STUkkkkkk","id": 98441370,"node_id": "U_kgDOBd4Ymg","avatar_url": "https://avatars.githubusercontent.com/u/98441370?v=4","gravatar_id": "","url": "https://api.github.com/users/STUkkkkkk","html_url": "https://github.com/STUkkkkkk","followers_url": "https://api.github.com/users/STUkkkkkk/followers","following_url": "https://api.github.com/users/STUkkkkkk/following{/other_user}","gists_url": "https://api.github.com/users/STUkkkkkk/gists{/gist_id}","starred_url": "https://api.github.com/users/STUkkkkkk/starred{/owner}{/repo}","subscriptions_url": "https://api.github.com/users/STUkkkkkk/subscriptions","organizations_url": "https://api.github.com/users/STUkkkkkk/orgs","repos_url": "https://api.github.com/users/STUkkkkkk/repos","events_url": "https://api.github.com/users/STUkkkkkk/events{/privacy}","received_events_url": "https://api.github.com/users/STUkkkkkk/received_events","type": "User","site_admin": false,"name": "小坤(Stukk)","company": null,"blog": "","location": null,"email": null,"hireable": null,"bio": "学习!","twitter_username": null,"public_repos": 6,"public_gists": 0,"followers": 0,"following": 1,"created_at": "2022-01-26T03:23:04Z","updated_at": "2024-03-02T11:57:33Z","private_gists": 0,"total_private_repos": 2,"owned_private_repos": 2,"disk_usage": 33800,"collaborators": 0,"two_factor_authentication": false,"plan": {"name": "free","space": 976562499,"collaborators": 0,"private_repos": 10000}
}

我们就可以封装这些数据进行登录啦!

代码:

//        获取github用户信息String userInfoURL = gitHubConstants.getUserInfoURL(); //获取用户登录信息的请求地址String userInfo = HttpRequest.get("https://api.github.com/user").header(Header.AUTHORIZATION, "token " + accessToken).header("X-GitHub-Api-Version", "2022-11-28").execute().body();JSONObject userInfoJson = JSONObject.parseObject(userInfo);String githubId = userInfoJson.getString("id"); //这个是github的idLambdaQueryWrapper<User> userLambdaQueryWrapper =  new LambdaQueryWrapper<>();userLambdaQueryWrapper.eq(User::getGithubId,githubId);User user = this.getOne(userLambdaQueryWrapper);if(user != null){// 3. 记录用户的登录态request.getSession().setAttribute(USER_LOGIN_STATE, user);return this.getLoginUserVO(user);}
//接下来看你的业务去写代码了
2.4 根据access_token获取用户邮箱

和上面一样,就是把user换成emails

Authorization: token ${access_token}
GET https://api.github.com/emails

响应结果:
 

[{"email": "xxx@qq.com","primary": true,"verified": true,"visibility": "private"},{"email": "xxx@users.noreply.github.com","primary": false,"verified": true,"visibility": null}
]

和前面的user一样,不赘述了。

3. 将Github用户信息与数据库进行比对,进行登录注册

        到此我们已经拿到了Github用户的信息,我们通过比对githubId来看看是否出现在数据库中,不在的话就进行注册,存在的话就登陆操作。

        比如我们可以数据库记录的是用户的id,githubId,用户名,邮箱等等如果用户第一次登录,插入一条记录,如果不是就进行数据库数据的比对进行登录,如果有错误,终止登录流程并进行提示。没有错误就把页面重定向到对应的前端页面,并且把用户信息返回给前端,这样就完成了第三方登录了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WhatsApp解封方法和防封技巧分享,内附解封话术!

WhatsApp 已成为外贸人员不可或缺的沟通工具&#xff0c;它不仅加速了全球范围内的客户沟通&#xff0c;还提供了一个方便快捷的社交媒体营销平台。然而&#xff0c;面对WhatsApp账号被封的问题&#xff0c;许多外贸人常常感到束手无策。本文旨在分享有效的WhatsApp解封方法&am…

西湖大学赵世钰老师【强化学习的数学原理】学习笔记2节

强化学习的数学原理是由西湖大学赵世钰老师带来的关于RL理论方面的详细课程&#xff0c;本课程深入浅出地介绍了RL的基础原理&#xff0c;前置技能只需要基础的编程能力、概率论以及一部分的高等数学&#xff0c;你听完之后会在大脑里面清晰的勾勒出RL公式推导链条中的每一个部…

BKP备份寄存器RTC实时时钟

文章目录 BKP简介相关引脚BKP基本结构 RTC简介RTC框图三种时钟源RTC基本结构 硬件电路RTC操作注意事项 BKP简介 BKP&#xff08;Backup Registers&#xff09;备份寄存器BKP可用于存储用户应用程序数据。当VDD&#xff08;2.0~ 3.6V&#xff09;电源被切断&#xff0c;他们仍然…

【QT】ROS2 Humble联合使用QT教程

【QT】ROS2 Humble联合使用QT教程 文章目录 【QT】ROS2 Humble联合使用QT教程1. 安装ROSProjectManager插件2. 创建ROS项目3.一个快速体验的demoReference 环境的具体信息如下&#xff1a; ubunt 22.04ros2 humbleQt Creator 13.0.0ROS ProjectManager 13.0.0 本文建立在已经…

MT3030 天梯赛

跟MT3029战神小码哥类似&#xff0c;都是贪心堆。注意开long long 这里的堆顶为战斗力最小的&#xff0c;便于贪心的反悔操作。先按容忍度从大到小排序&#xff08;q中总容忍度取决于最小的容忍度&#xff09;&#xff0c;再向q中存数&#xff0c;存到不能容忍之后再把堆顶踢出…

深度学习-线性回归+基础优化算法

目录 线性模型衡量预估质量训练数据参数学习训练损失最小化损失来学习参数显式解 总结基础优化梯度下降选择学习率 小批量随机梯度下降选择批量大小 总结线性回归的从零开始实现实现一个函数读取小批量效果展示这里可视化看一下 线性回归从零开始实现线性回归的简洁实现效果展示…

静态住宅IP代理VS动态住宅IP代理,该如何选择?

在网络安全和数据采集领域&#xff0c;代理服务已经成为一个必不可少的工具。在IP代理服务中&#xff0c;静态住宅代理和动态住宅代理是两种常见的代理类型。今天就为大家详细介绍静态住宅代理与动态住宅代理的差异。 首先我们来看什么是静态住宅IP&#xff0c;这种IP地址可以被…

硅酸盐玻璃反应离子刻蚀在光学微系统的应用前景

引言 微光学元件和复杂光学微系统需要超精密制造工艺。最大容许粗糙度由所用波长λ的分数定义&#xff0c;例如λ或更好&#xff0c;而元件的整体尺寸和形状可以容易地达到毫米或厘米范围。在RIE过程中&#xff0c;材料传输是通过离子和反应气体与等离子体反应器表面的物理和化…

Spring Boot项目中的ASCII艺术字

佛祖保佑&#xff1a; ${spring-boot.formatted-version} ———————————————————————————————————————————————————————————————————— // _ooOoo_ …

分享爱,分享精彩瞬间,分享5款实用软件

分享爱&#xff0c;分享时光&#xff0c;分享精彩瞬间&#xff0c;大家好&#xff0c;我是互联网的搬运工&#xff0c;今天继续给大家带来几款好用的软件。 1. 数据分析——Chartistic ​ Chartistic是一款功能强大的数据分析可视化工具&#xff0c;它提供了丰富的图表类型和…

C语言操作符和关键字

文章目录 操作符单目操作符sizeof&#xff08;类型&#xff09;强制类型转换 关系操作符、逻辑操作符、条件操作符逗号表达式 常见关键字typedefstaticstatic修饰局部变量static修饰全局变量static修饰函数 register寄存器关键词define定义常量和宏 操作符 单目操作符 C语言中…

R-Tree原理及实现代码

目录 一.引言 二.R-Tree的基本原理 插入操作 查询操作 删除操作 平衡操作 三. 节点分裂 线性分裂 二次分裂 增量分裂 四.查询 范围查询 最近邻查询 五.最新研究进展 六.C语言实现示例 七. 实际案例分析 八.总结 一.引言 在计算机科学领域&#xff0c;R-Tree是…

基于 Spring Boot 博客系统开发(一)

基于 Spring Boot 博客系统开发&#xff08;一&#xff09; 本系统是简易的个人博客系统开发&#xff0c;为了更加熟练地掌握SprIng Boot 框架及相关技术的使用。&#x1f913;&#x1f913;&#x1f913; 基于 Spring Boot 博客系统开发&#xff08;二&#xff09;&#x1f4…

聊聊.NET Core处理全局异常有那些方法

简述 处理全局异常的方法有IExceptionFilter&#xff08;异常处理&#xff09;&#xff0c;使用中间件异常处理&#xff0c;使用框架自带异常中间件等。考点 考察对异常处理方式的熟悉程度和广度&#xff0c;以及对中间件、过滤器熟练程度。 下面分别具体介绍三种处理异常的…

Spring Cloud学习笔记(Feigh):简介,实战简单样例

这是本人学习的总结&#xff0c;主要学习资料如下 - 马士兵教育 1、Netflix Feign简介2、Open Feign的简单样例2.1、dependency2.2、代码样例 1、Netflix Feign简介 Netfilx Feign是用来帮助发送远程服务的&#xff0c;它让开发者觉得调用远程服务就像是调用本地方法一样&…

计算机系列之进程调度、死锁、存储管理、设备管理、文件管理

11、进程调度-死锁-存储管理-固定分页分段 1、进程调度 进程调度方式是指当有更高优先级的进程到来时如何分配CPU。分为可剥夺和不可剥夺两种&#xff0c;可剥夺指当有更高优先级进程到来时&#xff0c;强行将正在运行进程的CPU分配给高优先级进程&#xff1b;不可剥夺是指高…

分享一些常用的内外网文件传输工具

内外网隔离后的文件传输是网络安全领域中一个常见而又重要的问题。随着信息技术的快速发展&#xff0c;网络安全问题日益凸显&#xff0c;内外网隔离成为了许多企业和组织保护内部信息安全的重要手段。然而&#xff0c;内外网隔离后如何有效地进行文件传输&#xff0c;成为了摆…

专利视角下的量子竞赛:《2024全球专利格局白皮书》

2024年1月&#xff0c;欧洲量子产业联盟&#xff08;QuIC&#xff09;发布了题为《全球量子技术专利格局描述》的综合白皮书。 该文件以透明的视角展示了当今的知识产权格局&#xff0c;包括知识产权持有人的地理分布。该文件由 QuIC 知识产权&#xff08;IP&#xff09;与贸易…

3DTiles特性与内容解析

一篇19年整理的比较老的笔记了。更多精彩内容尽在数字孪生平台。 瓦片种类 3DTiles瓦片有多种类型&#xff1a; b3dm(Batched 3D Model&#xff0c;批量3D模型) b3dm瓦片存储了多个个体&#xff0c;b3dm中的glb代表的实际对象应该具有相同的种类但是可能数据内容不同。b3dm…

ABAP开发:SAPscript表单设计及打印简介

在SAP ERP系统应用中&#xff0c;通常利用Forms表单来定制诸如发票、支票及标签之类的特殊文档的打印格式。这些Forms用来描述文档页面中的信息结构&#xff0c;比如地址抬头、item行、页脚等等&#xff0c;Forms设计就是要确定这些文档的输出格式。 利用SAPscript工具进行Form…