SpringBoot + Vue实现Github第三方登录

本文主要是介绍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,用户名,邮箱等等如果用户第一次登录,插入一条记录,如果不是就进行数据库数据的比对进行登录,如果有错误,终止登录流程并进行提示。没有错误就把页面重定向到对应的前端页面,并且把用户信息返回给前端,这样就完成了第三方登录了!

这篇关于SpringBoot + Vue实现Github第三方登录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/944131

相关文章

【前端】CSS基础(3)

文章目录 前言1. CSS常用元素属性1.1 字体属性1.1.1 字体1.1.2 字体大小1.1.3 字体颜色1.1.4 字体粗细1.1.5 文字样式 前言 这篇博客仅仅是对CSS的基本结构进行了一些说明,关于CSS的更多讲解以及HTML、Javascript部分的讲解可以关注一下下面的专栏,会持续更新的。 链接: Web前端学习专栏 下面我对这个专栏的内容进行几点说明:

spark自定义函数实现

场景:由于系统函数无法满足实际开发需求,需要通过自定义函数来实现 示例: package sparkimport org.apache.spark.sql.{Row, SparkSession}import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}im

《算法导论》学习笔记之Chapter10---队列的数组实现

紧接上一篇文章,本文记录数组实现队列的实现 队列的定义:顺序存储结构存储的队列称为顺序队列,是一个内部存储元素按顺序排列的列表,遵循先进先出原则。 需要理解的是队列的两个定义:队头front和队尾rear。两者都是指向队列元素的指针,队头指针始终指向队列最先进去的元素的前一个下标位置,初始值可设为-1。队尾指向队列最后进去的元素下标,初始值常为0。     判断队列是否为空的条件是:队头指针

IDEA 使用Alibaba Cloud Toolkit 实现远程 自动部署

安装插件 maven方式部署 配置服务器主机信息 配置发布到主机 单击Select 单击run 就可以将选择module的jar文件上传到服务器的指定位置了 Alibaba Cloud Toolkit 上传文件的方式部署

每天Get一个小技巧:用DolphinScheduler实现隔几天调度

转载自tuoluzhe8521 这篇小短文将教会你如何使用Apache DolphinScheduler实现隔几天调度,有此需求的小伙伴学起来! 1 场景分析 DolphinScheduler定时器模块-定时调度时每3秒|每3分钟|每3天这种定时,不能够跨分钟,跨小时,跨月,每次跨月等都会从每个月的第1天(第几天开始可以设定)开始重新计时。 为解决此问题,可以采用整天运行,并使用Dol

8.2 GOOGLE(SAML应用)登录联携AWS用户池(Amazon Cognito)

GOOGLE(SAML应用)登录联携AWS用户池(Amazon Cognito) 目录一、参考资料二、创建和配置AWS用户池1. 创建用户池2. 在用户池中创建联合身份提供商3. 在用户池中创建应用程序集成 三、创建和配置GOOGLE SAML应用1. 创建GOOGLE SAML应用 四、登录测试 目录 业务流程:实现用AWS提供的谷歌登录UI,以谷歌用户身份登录后,谷歌用户

2024OD机试卷-游戏分组 (java\python\c++)

题目:游戏分组 题目描述 部们准备举办一场 王者荣耀 表演赛,有 10 名游戏爱好者参与,分为两队,每队 5 人。 每位参与者都有一个评分,代表着他的游戏水平。为了表演赛尽可能精彩,我们需要把 10 名参赛者分为实力尽量相近的两队。 一队的实力可以表示为这一队 5 名队员的评分总和。 现在给你 10 名参与者的游戏水平评分,请你根据上述要求分队,最后输出这两组的实力差绝对值。 例:10 名参赛

那些年我与c++的叫板(一)--string类自实现

引子:我们学习了c++中的string类,那我们能不能像以前数据结构一样自己实现string类呢?以下是cplusplus下的string类,我们参考参考! 废话不多说,直接代码实现:(注意函数之间的复用!) #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include<iostream> #include<assert.h> usin

webpack5零基础入门-14提取css为单独文件

1.背景 Css文件目前被打包到JS文件中,当JS文件加载时,会尝试创建一个style标签来生成样式,这样对于网站来说,会出现闪屏的现象,用户体验不好。我们应该是单独的Css文件,通过link标签来加载性能才好。 2.下载包 npm install --save-dev mini-css-extract-plugin 3.在webpack.config.js中引入 4.去掉style

NVM安装及VUE创建项目的N种方式

VUE 参考官网:https://cli.vuejs.org/zh/guide/ 目录 NVM安装 1.卸载node.js 2.安装nvm ​编辑​ 3.配置 4.使用nvm安装node.js 5.nvm常用命令 创建VUE项目 1.使用vue init 创建vue2(不推荐) 2.使用vue create创建vue2和3(较推荐) 3.使用npm create vu