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…

大宋咨询(深圳第三方绩效评估)谈关于消费者满意度研究的概念

消费者满意度研究是一种评估消费者对于特定产品、服务或购物体验的满意程度的方法。它旨在了解消费者在购买和使用过程中的感受、意见和反馈&#xff0c;从而衡量企业的产品、服务质量以及顾客关系管理的效果。消费者满意度研究对于企业了解消费者需求、改进产品和服务&#xf…

使用Selenium爬取目标网站被识别的解决之法

在进行网络数据抓取和爬取时&#xff0c;Selenium是一个常用的工具&#xff0c;它可以模拟人类用户的行为&#xff0c;自动化地操作浏览器进行页面的访问和数据的提取。然而&#xff0c;随着网站对爬虫的检测能力不断提升&#xff0c;很多爬虫程序在运行过程中经常会遭遇被目标…

[DEMO]给两个字符串取交集的词语

要求&#xff1a;2个英文字符串中&#xff0c;取相同的大于等于4个字母的词组 比如&#xff1a; 字符串1&#xff1a;" xingMeiLingabcdef WorldHello", 字符串2&#xff1a;"mnjqlup WorldLingLing xingMeiLingHello" 获取交接&#xff1a; [xingMeiLing…

Faiss:高效相似性搜索与聚类的利器

Faiss 是一个针对大规模向量集合的相似性搜索库&#xff0c;由 Facebook AI Research 开发。它提供了一系列高效的算法和数据结构&#xff0c;用于加速向量之间的相似性搜索&#xff0c;特别是在大规模数据集上。本文将介绍 Faiss 的原理、核心功能以及如何在实际项目中使用它。…

Vue3 中 defineProps 怎么设置默认值?

在 Vue3 中&#xff0c;我们经常需要使用 defineProps 来定义组件的属性&#xff0c;但是如何设置这些属性的默认值呢&#xff1f; 这是一个常见的问题&#xff0c;特别是在开发过程中&#xff0c;我们希望能够为组件的属性提供一些默认值&#xff0c;以便在未传递属性值时能够…

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

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

LangChain入门教程 - 基本问答

自己的学习记录&#xff0c;想到哪里写到哪里。下面用LC指代LangChain。更详细的内容请查看LangChain中文网。 LLM和ChatModel有什么区别&#xff1f; 这是使用LC首先会遇到的问题。 在 Langchain 中&#xff0c;ChatModel 和 LLM&#xff08;Large Language Model&#xff…

鸿蒙原生应用元服务开发-Web管理位置权限

Web组件提供位置权限管理能力。开发者可以通过onGeolocationShow()接口对某个网站进行位置权限管理。Web组件根据接口响应结果&#xff0c;决定是否赋予前端页面权限。获取设备位置&#xff0c;需要开发者配置ohos.permission.LOCATION权限。 在下面的示例中&#xff0c;用户点…

BKP备份寄存器RTC实时时钟

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

【数学题】俄罗斯竞赛题笔算开平方√446224

这里写目录标题 一级目录二级目录三级目录 一、题目二、解题方式1&#xff1a;设元配方三、解题方式2&#xff1a;逐位逼近①因式分解②数字范围分析③求十位③求个位④整理 四、解题方式3&#xff1a;逐位逼近2①因式分解②数字范围分析③假设个位是3&#xff0c;设十位m,则③…

学生管理系统代码

学生管理系统代码 好好看&#xff0c;好好学&#xff0c;知识点的部分看不懂就多查。 内容很多&#xff0c;仔细看。 #include <stdio.h> #include <stdlib.h> #define M 100 #define N 10//定义学生相关信息结构体 typedef struct stu {char sn[13];char name[9…

【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 本文建立在已经…

3D头模加载

目录 psbody加载 psbody示例 trimesh加载 openmesh psbody加载 codetalker from psbody.mesh import Meshif cfg.dataset "BIWI":template_file os.path.join(cfg.data_root, "BIWI.ply")elif cfg.dataset "vocaset":template_file os…

git bash上传本地文件报错debug

报错信息 remote: error: Trace: 9621c90b124fcb8e353c79fc4011b62f684d0850872e2a5a9ee4bdf1e8092198 remote: error: See https://gh.io/lfs for more information. remote: error: File res_checkpoint/3_17_heart.pth is 357.69 MB; this exceeds GitHubs file size limit…

MT3030 天梯赛

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

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

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

MATLAB初学者入门(12)—— 模拟退火算法

模拟退火&#xff08;Simulated Annealing, SA&#xff09;是一种概率性搜索技术&#xff0c;用于寻找给定函数的全局最优解。该算法受到物理学中固体退火过程的启发&#xff0c;通过模拟物质冷却过程中粒子的随机运动&#xff0c;来逐步寻找优化解。它允许在搜索过程中偶尔接受…

【Java那些事】@TableField对字段的自动填充

问题&#xff1a;当你有个对象User时&#xff0c;这个User对象的属性还有类似createTime &#xff0c;updateTime的属性&#xff0c;每次创建这个对象都要设置createTime &#xff0c;updateTime&#xff0c;对这个对象User进行操作又要来更新它的updateTime&#xff0c;是不是…

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

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