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的id
        LambdaQueryWrapper<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.mfbz.cn/a/579440.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WebGIS面试题(第六期)-GeoServer

WebGIS面试题&#xff08;第六期&#xff09; 以下题目仅为部分题目&#xff0c;全部题目在公众号 {GISer世界} &#xff0c;答案仅供参考!!! 因为本人之前做过相关项目用到了GeoServer&#xff0c;因此在简历上写了熟悉GeoServer。所以在相关面试中都有问到&#xff0c;所以我…

【项目】仿muduo库One Thread One Loop式主从Reactor模型实现高并发服务器(Http板块)

【项目】仿muduo库One Thread One Loop式主从Reactor模型实现高并发服务器&#xff08;Http板块&#xff09; 一、思路图二、Util板块1、Splite板块&#xff08;分词&#xff09;&#xff08;1&#xff09;代码&#xff08;2&#xff09;测试及测试结果i、第一种测试ii、第二种…

[论文阅读] 3D感知相关论文简单摘要

Adaptive Fusion of Single-View and Multi-View Depth for Autonomous Driving 提出了一个单、多视图融合深度估计系统&#xff0c;它自适应地集成了高置信度的单视图和多视图结果 动态选择两个分支之间的高置信度区域执行融合 提出了一个双分支网络&#xff0c;即一个以单…

查看笔记本电池容量/健康状态

1. 打开命令行提示符 快捷键“win R”后输入“cmd” 2. 在命令提示符中输入命令 “powercfg /batteryreport" 并回车 3. 查看文件 最后就可以看到笔记本的电池使用报告了

Promises: JavaScript异步编程的救星

Promises: JavaScript异步编程的救星 Promises&#xff08;承诺&#xff09;是JavaScript中处理异步操作的一种机制&#xff0c;它提供了一种更优雅和可读性更高的方式来处理异步代码。Promises的实现原理基于一种称为"Promise/A"规范的约定&#xff0c;该规范定义了…

[蓝桥杯2024]-Reverse:rc4解析(对称密码rc4)

无壳 查看ida 这里应该运行就可以得flag&#xff0c;但是这个程序不能直接点击运行 按照伪代码写exp 完整exp&#xff1a; keylist(gamelab) content[0xB6,0x42,0xB7,0xFC,0xF0,0xA2,0x5E,0xA9,0x3D,0x29,0x36,0x1F,0x54,0x29,0x72,0xA8, 0x63,0x32,0xF2,0x44,0x8B,0x85,0x…

visual studio2022,开发CMake项目添加rabbitmq库,连接到远程计算机并进行开发于调试

1.打开visual studio installer 。安装“用于 Windows 的 C CMake 工具” 2.新建CMake项目 3.点击VS的“工具”—>"选项“—>“跨平台”—>”连接管理器“,添加远程计算机。用来将VS编辑的代码传到服务器进行编译–连接—运行&#xff08;调试&#xff09;。 …

BIO、NIO与AIO

一 BIO 同步并阻塞(传统阻塞型)&#xff0c;服务器实现模式为一个连接一个线程&#xff0c;即客户端有连接请求时服务器端就需要启动一个线程进行处理. BIO&#xff08;Blocking I/O&#xff0c;阻塞I/O&#xff09;模式是一种网络编程中的I/O处理模式。在BIO模式中&#xf…

鸿蒙内核源码分析(任务调度篇) | 任务是内核调度的单元

任务即线程 在鸿蒙内核中&#xff0c;广义上可理解为一个任务就是一个线程 官方是怎么描述线程的 基本概念 从系统的角度看&#xff0c;线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源&#xff0c;并独立于其它线程运行。 鸿蒙内核每个…

[蓝桥杯2024]-PWN:fd解析(命令符转义,标准输出重定向)

查看保护 查看ida 这里有一次栈溢出&#xff0c;并且题目给了我们system函数。 这里的知识点没有那么复杂 完整exp&#xff1a; from pwn import* pprocess(./pwn) pop_rdi0x400933 info0x601090 system0x400778payloadb"ca\\t flag 1>&2" print(len(paylo…

SAP PP学习笔记07 - 作业手顺(工艺路线Routing)

上一章讲了BOM的相关知识。 SAP PP学习笔记07 - 简单BOM&#xff0c;派生BOM&#xff0c;多重BOM&#xff0c;批量修改工具 CEWB_sap半成品有多个bom-CSDN博客 本章来讲作业手顺&#xff08;工艺路线Routing&#xff09;的相关知识。 1&#xff0c;作业手顺(工艺路线 Routing…

四、线段、矩形、圆、椭圆、自定义多边形、边缘轮廓和文本绘制(OpenCvSharp)

功能实现&#xff1a; 对指定图片上进行绘制线段、矩形、圆、椭圆、自定义多边形、边缘轮廓以及自定义文本 一、布局 用到了一个pictureBox和八个button 二、引入命名空间 using System; using System.Collections.Generic; using System.Drawing; using System.Windows.F…

Dockerfile镜像构建实战

一、构建Apache镜像 cd /opt/ #建立工作目录 mkdir /opt/apache cd apache/vim Dockerfile #基于的基础镜像 FROM centos:7 #维护镜像的用户信息 MAINTAINER this is apache image <cyj> #镜像操作指令安装Apache软件 RUN yum install -y httpd #开启80端口 EXPOSE 80 #…

远程桌面连接不上个别服务器的问题分析与解决方案

在日常的IT运维工作中&#xff0c;远程桌面连接&#xff08;RDP&#xff0c;Remote Desktop Protocol&#xff09;是我们经常使用的工具之一&#xff0c;用于管理和维护远程服务器。然而&#xff0c;有时我们可能会遇到无法连接到个别服务器的情况。针对这一问题&#xff0c;我…

《Kafka 3.x.x 入门到精通》

Kafka 3.x.x 入门到精通 Kafka是一个由Scala和Java语言开发的&#xff0c;经典高吞吐量的分布式消息发布和订阅系统&#xff0c;也是大数据技术领域中用作数据交换的核心组件之一。以高吞吐&#xff0c;低延迟&#xff0c;高伸缩&#xff0c;高可靠性&#xff0c;高并发&#x…

【论文浅尝】Porting Large Language Models to Mobile Devices for Question Answering

Introduction 移动设备上的大型语言模型(LLM)增强了自然语言处理&#xff0c;并支持更直观的交互。这些模型支持高级虚拟助理、语言翻译、文本摘要或文本中关键术语的提取(命名实体提取)等应用。 LLMs的一个重要用例也是问答&#xff0c;它可以为大量的用户查询提供准确的和上…

LeetCode 热题 100 题解:二叉树部分(1 ~ 5)

题目一&#xff1a;二叉树的中序遍历&#xff08;No. 948&#xff09; 94. 二叉树的中序遍历 - 力扣&#xff08;LeetCode&#xff09; 题目难度&#xff1a;简单 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;roo…

【Django】初识Django快速上手

Django简介 Django是一个高级的、开源的Python Web框架&#xff0c;旨在快速、高效地开发高质量的Web应用程序 https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Django/Introduction 安装Django pip install Django如果要知道安装的Django的版本&#xff0c;可…

关于两步到位Chrome永久停止更新

全程就两个步骤&#xff01;&#xff01;敲重点&#xff01;&#xff01;&#xff01; 好使记得点赞关注我&#xff01; 1.找到Chrome包下的hosts文件 默认路径大概是 C:\Windows\System32\drivers\etc\hosts &#xff0c;不记得了可以通过Everything查找 在hosts 文件中 …

移动端日志采集与分析最佳实践

前言 做为一名移动端开发者&#xff0c;深刻体会日志采集对工程师来说具有重要意义&#xff0c;遇到问题除了 debug 调试就是看日志了&#xff0c;通过看日志可以帮助我们了解应用程序运行状况、优化用户体验、保障数据安全依据&#xff0c;本文将介绍日志采集的重要性、移动端…