【深入浅出 Spring Security(十二)】使用第三方(Github)授权登录

news2024/11/16 1:48:11

使用第三方(Github)授权登录

  • 一、OAuth2 简单概述
  • 二、OAuth2 四种授权模式之授权码模式
  • 三、Github 授权登录
    • 准备工作
    • 创建 Spring Boot 项目
    • Vue 测试代码
    • 测试效果

(Github授权登录的具体操作在目录第三“章”)

一、OAuth2 简单概述

下面是《深入浅出Spring Security》书中的一段概述:

OAuth 是一个开放标准(现在所说的 OAuth 一般都是指 OAuth2,即 2.0 版本),可以理解为是一种协议,该标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像、照片、视频等),并且在这个过程中无须将用户名和密码提供给第三方应用。通过令牌(token)可以实现这一功能,每一个令牌授权一个特定的网站在特定的时段内允许访问特定的资源。

OAuth 让用户可以授权第三方网站灵活访问它们存储在另外一些资源服务器上的特定信息,而非所有内容。对于用户而言,我们在互联网应用中最常见的 OAuth 应用就是各种第三方登录,例如:QQ授权登录、微信授权登录、下面要解释的Github 授权登录等等。

注意:这里所述的第三方应用是相对而言的。例如用户想通过 QQ 登录今日头条,这时相对于QQ而言,今日头条就是第三方应用,对今日头条而言,QQ就是第三方应用。当今日头条通过QQ授权登录时,QQ 不会把 用户名/密码 给今日头条,只会传一种 token 令牌,允许它访问 QQ用户中的一些信息(一般是只读信息)。

二、OAuth2 四种授权模式之授权码模式

OAuth2 协议一共支持四种不同的授权模式:授权码模式、简化模式、密码模式、客户端模式。下面解释一下最安全、使用最广泛的一种 OAuth2 权限模式——授权码模式。以下是授权流程图:

在这里插入图片描述

  1. 用户点击登录链接(按钮),系统会将用户导入授权服务器的登录页面,对应着A(用户-》浏览器-》认证服务器响应给浏览器);
  2. 用户选择是否给予授权,这一阶段进行的是用户选择认证阶段,对应着B。
  3. 如果用户同意授权,则授权服务器会将页面重定向到 redirect_uri 指定的地址,同时携带一个授权码参数,带着授权码去重定向,这个时候是向授权服务器请求令牌,在后端进行,在Spring Security 中即对应着认证操作,对应着步骤C。
  4. 授权服务器对参数进行校验之后,即认证成功后会返回 Access Token 和 Refresh Token,即Authentication,这个过程对应着E。
  5. 通过了认证就可以向资源服务器请求资源了。

授权码模式被认为是最安全的一种模式,是因为这种模式的 Access Token 不会经过浏览器,是直接从项目的后端获取,并从后端发送到资源服务器上,这样就很大程度上减少了 Access Token 泄露的风险。

redirect_uri :该参数表示在登录校验成功/失败后(例如Github校验成功或失败后),跳转的地址,跳转的时候,还会携带上一个授权码参数,开发者再根据这个授权码获取 Access Token。Spring Security 中跳转的地址应该为 /login/oauth2/code/*, * 表示的是第三方授权应用名,如需要github授权登录,那它的 redirect_uri 应该为 /login/oauth2/code/github

三、Github 授权登录

准备工作

首先需要将第三方应用的信息注册到 Github 上。登录自己的Github账户,点击 Settings。

在这里插入图片描述
点击 New OAuth app,添加新的应用。
在这里插入图片描述需填写的信息概述:

  • application name:应用名称
  • Homepage URL:项目主页面
  • Authorization callback URL:认证成功后的回调页面,默认的回调 URL 地址模版为 {baseUrl}/login/oauth2/code/{registrationId},其中 registration 是ClientRegistration 的唯一标识符,则在接下来的 SpringBoot 项目中就不必提供回调接口了(但写上也无妨)。

以下是我测试的注册内容(然后点击注册):

在这里插入图片描述
注册成功后会获取到两个参数,Client IDClient Secret,保存这俩参数,在配置项目中需要使用。

在这里插入图片描述

创建 Spring Boot 项目

  1. 需要的起步依赖
    在这里插入图片描述
  2. 配置 oauth-Client(application.yml):
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: 57b238e8791efafaead6
            client-secret: 33b3e36f0e464a5c13426fe59e61230ef72a1a47
            redirect-uri: http://localhost:8080/login/oauth2/code/github
server:
  port: 8080
  servlet:
    context-path: /
  1. 创建测试接口(TestController)
@RestController
public class TestController {

    @GetMapping("/test")
    public DefaultOAuth2User test(){
        System.out.println("Test Result~~~~");
        return (DefaultOAuth2User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
    
}
  1. 创建 SpringSecurity 配置类(SecurityConfig)
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2Login()
                .failureHandler((req,res,e)->{
                    res.setContentType("text/html;charset=utf-8");
                    PrintWriter out = res.getWriter();
                    out.print("认证失败");
                })
                .and()
                .cors()
                .configurationSource(this.corsConfigurationSource())
                .and()
                .csrf((config)->{
                    config.disable();
                })
                .build();
    }

    private CorsConfigurationSource corsConfigurationSource(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedHeader("*"); // 这个得加上,一些复杂的请求方式会带有header,不加上跨域会失效。
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addExposedHeader("*");
        corsConfiguration.addAllowedOriginPattern("http://localhost:5173");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }
    
}

Vue 测试代码

这里再提一嘴,不然前端部分的超链接地址看不懂:

后端配置使用 OAuth2Login 授权登录时,Spring Security 中有俩过滤器会开启——OAuth2AuthorizationRequestRedirectFilterOAuth2LoginAuthenticationFilter。例如:重定向到Github提供的授权页面即是OAuth2AuthorizationRequestRedirectFilter过滤的;认证请求,授权成功跳转URL的即是OAuth2LoginAuthenticationFilter过滤的。
在这里插入图片描述在这里插入图片描述

所以那授权登录按钮我写的地址是:http://localhost:8080/oauth2/authorization/github,OAuth2AuthorizationRequestRedirectFilter 会过滤掉它然后重定向到Github提供的授权页面…

<script setup>
import { ref } from 'vue'
import axios from '../utils/index.js'

function test(){
    axios.get(`/test`,{
        withCredentials: true,   //设置跨域的时候传递cookie,需要服务端的配合
    }).then(res=>{
        console.log(res)
        content.value = res
    }).catch(err=>{
        console.log(666)
        console.log(err)
    })
}

</script>

<template>
    <div>
        <el-button type="info" round>
            <el-link href="http://localhost:8080/oauth2/authorization/github"> github </el-link>
        </el-button>
        <br><br>
        <button @click="test">发送测试请求</button><br><br>
    </div>
</template>

测试效果

这里不是实际的效果(实际效果应该是:点击"http://localhost:8080/oauth2/authorization/github"超链接后,会返回302,重定向到Github授权页面,授权成功后又会重定向到配置的 redirect_uri(http://localhost:8080/login/oauth2/code/github?code=???&state=???),这个时候就是关 OAuth2LoginAuthenticationFilter 的事了,这里会根据 redirect_uri 中请求参数携带的授权码 code,向Github授权服务器的https://github.com/login/oauth/access_token 接口去请求 Access Token,拿到AccessToken后,再向 https://api.github.com/user 地址发送请求,获取用户信息,前面是浏览器可见的,后面获取令牌是在后端完成的,是用户不可见的)。

请添加图片描述
下面是我遇到的一些疑问,问的ChatGpt的,如果有同样的疑虑可以看看:

在这里插入图片描述
测试中间会有跳转Github授权登录页面(https://github.com/login/oauth/authorize?..),请求 Access Token 也会访问Github(https://github.com/login/oauth/access_token),比较慢,我不耐烦就疯狂点,就报下面错了(大家可别学我)。
在这里插入图片描述

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

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

相关文章

Spring Boot 优雅集成 Spring Security 5.7(安全框架)与 JWT(双令牌机制)

Spring Boot 集成 Spring Security &#xff08;安全框架&#xff09; 本章节将介绍 Spring Boot 集成 Spring Security 5.7&#xff08;安全框架&#xff09;。 &#x1f916; Spring Boot 2.x 实践案例&#xff08;代码仓库&#xff09; 介绍 Spring Security 是一个能够为基…

【CSDN创作纪念日】——博客小梦的“256”鸭~

博客小梦的创作纪念日&#x1f60e; 前言&#x1f64c;与CSDN的相遇浑水摸鱼的日常CSDN上的小小收获收获了 一群热爱编程&#xff0c;热爱创作的CSDN挚友创作上的小荣誉 憧憬未来 总结撒花&#x1f49e; &#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭…

【Spring】— Spring MVC简单数据绑定(一)

目录 Spring MVC数据绑定1.数据绑定概述2.简单数据绑定2.1 绑定默认数据类型2.2 绑定简单数据类型 Spring MVC数据绑定 1.数据绑定概述 在执行程序时&#xff0c;Spring MVC根据客户端请求参数的不同将请求消息中的信息以一定的方式转换并绑定到控制器类的方法参数中。这种将…

基于VMD-LSTM-IOWA-RBF的碳排放混合预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

第J3-1周:DenseNet算法 实现乳腺癌识别

目录 一、理论基础1.前言2.设计理念3.网络结构4.与其他算法效果对比 二、 前期准备1. 设置GPU2. 导入数据3. 划分数据集 三、搭建网络模型1. DenseLayer模块2. DenseBlock模块3. Transition模块4. 构建DenseNet5. 构建densenet121 四、 训练模型1. 编写训练函数2. 编写测试函数…

I/O多路复用+高性能网络模式

前言&#xff1a; 本篇文章将介绍客户端-服务端之间从最简单的Socket模型到I/O多路复用的模式演变过程&#xff0c;并介绍Reactor和Proactor两种高性能网络模式 文章内容摘自&#xff1a;小林Coding I/O多路复用高性能网络模式 . 传统Socket模型传统Socket模型的性能瓶颈多进程…

【Java基础学习打卡12】Java入门程序

目录 前言一、Java程序开发运行流程二、Java程序源代码编写三、Java程序源代码编译四、Java程序运行五、Java入门程序问题总结 前言 本文首先介绍Java程序开发运行基础流程&#xff0c;然后先进行程序源代码编写&#xff0c;然后对Java程序代码进行编译&#xff0c;最后要运行…

Python学习笔记(1)--环境搭建,开发工具PyCharm 安装及初步使用

传送门>B站黑马python入门教程 目录 1.Python环境安装搭建安装python基础包验证安装文件 2.hello world3.开发工具PyCharm 安装及初步使用安装基础设置 1.Python环境安装搭建 安装python基础包 首先,打开python 官网 https://www.python.org/ 下载windows版 下载后进行安装 …

Triton教程 --- 解耦后端和模型

Triton教程 — 解耦后端和模型 Triton系列教程: 快速开始利用Triton部署你自己的模型Triton架构模型仓库存储代理模型设置优化动态批处理速率限制器模型管理自定义算子 解耦后端和模型 Triton 可以支持为一个请求发送多个响应或为一个请求发送零个响应的后端和模型。 解耦的…

论文笔记--Prompt Consistency for Zero-Shot Task Generalization

论文笔记--Prompt Consistency for Zero-Shot Task Generalization 1. 文章简介2. 文章概括3 文章重点技术3.1 Prompt-based zero-shot task generalization3.2 Prompt Consistency Training3.3 如何防止遗忘和退化&#xff1f; 4. 文章亮点5. 原文传送门 1. 文章简介 标题&am…

【numpy模块上}——数据分析01

目录索引 介绍&#xff1a;用处与特点&#xff1a;构成&#xff1a;导包&#xff1a;创建数组&#xff1a; numpy常用方法&#xff1a;常用属性查看&#xff1a;*获取秩的大小&#xff1a;**获取数组形状&#xff1a;**获取元素个数&#xff1a;**获取元素类型&#xff1a;**获…

行为型设计模式10-解释器模式

&#x1f9d1;‍&#x1f4bb;作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 解释器模式 1、解释器模式介绍 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为设…

Kafka系列之:对源连接器的的Exactly-Once支持

Kafka系列之&#xff1a;对源连接器的的Exactly-Once支持 一、背景二、目标三、公共接口四、连接器 API 扩展五、REST API验证六、新指标七、计划变更八、任务计数记录九、重新平衡的准备十、源任务启动十一、领导者访问配置主题十二、用于隔离事务生产者的管理 API十三、解决了…

论文阅读 - SegFormer

文章目录 1 概述2 模型说明2.1 总体结构2.2 Hierarchical Transformer Encoder2.3 Lightweight All-MLP Decoder 3 SegFormer和SETR的比较参考资料 1 概述 图像分割任务和图像分类任务是非常相关的&#xff0c;前者是像素级别的分类&#xff0c;后者是图像级别的分类。基于分类…

不到3000块,搭建IT人的实验平台!性能可媲美服务器!

作为IT从业者&#xff0c;特别是运维这个岗位&#xff0c;没有自己的实验平台真的特别难受&#xff0c;那么如何搭建自己的实验平台呢&#xff1f;这是我最近思考并付诸实践的一个事情&#xff0c;最终找到了自己觉得比较可以的方案。 01 我的需求是什么&#xff1f; 大内存容量…

TypeScript——类(class)

ES6 中类的用法 下面我们先回顾一下 ES6 中类的用法&#xff0c;更详细的介绍可以参考 ECMAScript 6 入门 - Class 属性和方法 使用 class 定义类&#xff0c;使用 constructor 定义构造函数。 通过new生成新实例的时候&#xff0c;会自动调用构造函数。 class Person{con…

leetcode877. 石子游戏(动态规划-java)

石子游戏 leetcode877. 石子游戏题目描述暴力递归代码演示 动态规划 动态规划专题: leetcode877. 石子游戏 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/stone-game 题目描述 Alice 和 Bob 用几堆石子在做游戏。一共有…

HTTP与Fiddler使用

HTTP与Fiddler使用 HTTP与Fiddler使用FidderHTTP的报文结构&#xff1a;其他请求头User-agentReferer和OrigincookieHTTP状态码 HTTP与Fiddler使用 HTTP协议是使用十分广泛的应用层协议&#xff0c;也是一个可以由程序员进行设置的一个协议。该协议的结构规定了浏览器与万维网…

【C++】通讯录的基本实现,附有源码分享

目录 1、运行环境 2、系统实现功能 2.1菜单功能 2.2退出通讯录功能 2.3添加联系人功能 2.4显示联系人功能 2.5删除联系人功能 2.6查找联系人功能 2.7修改联系人功能 2.8清空联系人功能 2.9动态扩容功能 2.10选择优化功能 2.11文件操作 3、源码分享 1、运行环境 …

【备战秋招】每日一题:2023.04.26-华为OD机式-第三题-MC方块

在线评测链接:P1231 题目内容 MC最新版本更新了一种特殊的方块&#xff0c;幽匿催发体。这种方块能够吸收生物死亡掉落的经验并感染周围方块&#xff0c;使其变成幽匿块。Steve想要以此为基础尝试搭建一个经验仓库&#xff0c;他来到了创造超平坦模式&#xff0c;在只有草方块…