当前位置: 首页 > news >正文

一文入门SpringSecurity 5

目录

提示

Apache Shiro和Spring Security

认证和授权

RBAC

Demo

环境

Controller

引入Spring Security

初探Security原理

认证授权图示​编辑

图中涉及的类和接口

流程总结


提示

Spring Security源码的接口名和方法名都很长,看源码的时候要见名知意,有必要细看接口名和方法名,另外可以借助流程图,调试追踪代码,有助于理解学习!

Apache Shiro和Spring Security

​Spring Security是一个高度可定制的身份验证(认证)和访问控制(授权)框架,它是用于保护基于Spring的应用程序的实际标准,相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。

  • Shiro轻量级,不依赖Spring,是第三方框架,简单而灵活,可以用于非Web环境!
  • Security重量级,依赖Spring,控制粒度更细,老版本不能脱离Web,新版本可以
  • Spring Boot 2默认使用Security 5,要求JDK至少是8
  • Spring Boot 3默认使用Security 6,要求JDK至少是17
  • Security 5和Security 6的区别之一就是5到6废弃了WebSecurityConfigurerAdapter类,在Security 5编写配置类需要继承WebSecurityConfigurerAdapter并重写某些方法,但是在Security 6已经不需要了

Spring Security:升级已弃用的 WebSecurityConfigurerAdapter - spring 中文网

从 Spring Security 5 迁移到 Spring Security 6/Spring Boot 3 - spring 中文网

认证和授权

认证(Authentication):验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户

​授权(Authorization):经过认证后判断当前用户是否有权限进行某个操作

注:Authentication和Authorization拼写很像,有必要分清,后面看源代码方便!

RBAC

Role-Based Access Control 基于角色的访问控制

把权限打包给角色(角色拥有一组权限),给用户分配角色(用户拥有多个角色)

最少包括五张表 (用户表、角色表、用户角色表、权限表、角色权限表)

Demo

环境

Spring Boot:2.7.2

SpringSecurity:5+

JDK:1.8

Controller

@RestController
@RequestMapping("/admin")
public class AdminController {@GetMapping("/query")public String queryInfo(){return "I am a admin";}
}

 ​​​​​​可以直接访问

引入Spring Security

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

再次访问时默认出现了该登陆界面,默认用户是user,密码默认在控制台生成 ,成功登陆后才会放行。Spring Security默认拦截了除登录、退出之外的所有请求。显示的登录和退出表单是Security默认生成的。

(前端页面样式bootstrap.min.css是一个CDN地址,需要魔法,所以加载很慢) 

初探Security原理

Spring Security底层是基于Servlet的过滤器链,默认共有16个过滤器,这里面我们只需要重点关注两个过滤器即可:UsernamePasswordAuthenticationFilter负责登录认证,FilterSecurityInterceptor负责权限授权。

认证授权图示

图中涉及的类和接口

  • UsernamePasswordAuthenticationFilter类

    抽象类AbstractAuthenticationProcessingFilter的子类,是常用的用户名和密码认证方式的主要处理类,该类中将用请求信息封装为初步的Authentication(Authentication实际上是一个接口,它的实现类是UsernamePasswordAuthenticationToken),此时最多只有用户名和密码,在登录认证成功之后又会生成一个包含用户权限等信息的更全面的 Authentication 对象,然后把它保存在 SecurityContextHolder 所持有的 SecurityContext 中。

  • AuthenticationManager接口

    public interface AuthenticationManager {Authentication authenticate(Authentication authentication) throws AuthenticationException;
    }

    用来处理Authentication请求的接口。在其中只定义了一个方法 authenticate(),该方法只接收一个代表认证请求的 Authentication 对象作为参数,如果认证成功,则会返回一个封装了当前用户权限等信息的 Authentication 对象。

  • ProviderManager类

    public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean 

    AuthenticationManager接口的实现类AuthenticationManager接口不直接自己处理认证请求,而是委托给ProviderManager所配置的AuthenticationProvider 列表,而ProviderManager的作用就是管理这个AuthenticationProvider列表,管理的方式是通过for循环去遍历该列表,因为不同的登录逻辑(表单登录、qq登录、邮箱登录)是不一样的,那么AuthenticationProvider列表就要支持不同的Authentication。
    信息验证的逻辑都是在AuthenticationProvider里面,会依次使用每一个 AuthenticationProvider 进行认证,如果有一个 AuthenticationProvider 认证后的结果不为 null,则表示该 AuthenticationProvider 已经认证成功,之后的 AuthenticationProvider 将不再继续认证。然后直接以该 AuthenticationProvider 的认证结果作为 ProviderManager 的认证结果。如果所有的 AuthenticationProvider 的认证结果都为 null,则表示认证失败,将抛出一个 ProviderNotFoundException

  • AuthenticationProvider接口
    该接口被实现为抽象类AbstractUserDetailsAuthenticationProvider,然后DaoAuthenticationProvider类继承该抽象类,并拥有一个UserDetailsService的变量

    public abstract class AbstractUserDetailsAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAwarepublic class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider
  • UserDetailsService接口
    public interface UserDetailsService {UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    }
    加载用户数据的核心接口,可以自定义从数据库加载数据或者从内存加载临时用户(InMemory),登录认证的时候 Spring Security 会通过 UserDetailsService 的 loadUserByUsername() 方法获取对应的 UserDetails 类型的用户信息进行认证,认证通过后会将用户信息封装为UserDetails接口的实现类User并赋给认证通过的 Authentication 的 principal,然后再把该 Authentication 存入到 SecurityContext 中。
  • InMemoryUserDetailsManager类
    该类是UserDetailsService接口的实现类,作用是从内存中加载用户,也就是说用户是在代码中提前写好的,程序运行后被加载到内存,不是从数据库中取的没有持久化,如果是从数据库加载用户就不用这个类了。该类有一个方法是

    private User createUserDetails(String name, UserAttribute attr),返回值是User类型

  • UserDetails接口

    public interface UserDetails extends Serializable 

    提供用户核心信息的接口,通过 UserDetailsService 的 loadUserByUsername() 方法获取,然后将该 UserDetails 赋给认证通过的 Authentication 的 principal。

  • User类

    public class User implements UserDetails, CredentialsContainer 

    UserDetails接口的实现类,User类也是security的默认用户类,我们可以继承该类对其方法重写

  • SecurityContextHolder类

    用来保存 SecurityContext 的,SecurityContext 中含有当前正在访问系统的用户的详细信息。默认情况下,SecurityContextHolder 使用 ThreadLocal 来保存 SecurityContext,这也就意味着在处于同一线程中的方法中我们可以从 ThreadLocal 中获取到当前的 SecurityContext。因为线程池的原因,如果我们每次在请求完成后都将 ThreadLocal 进行清除的话,那么我们把 SecurityContext 存放在 ThreadLocal 中还是比较安全的。这些工作 Spring Security 已经自动为我们做了,即在每一次 request 结束后都将清除当前线程的 ThreadLocal。 

流程总结

用户填写的用户名密码传到后端,进入Security的过滤器链进行验证,验证流程为:

进入UsernamePasswordAuthenticationFilter,里面有一个attemptAuthentication方法,该方法会生成一个UsernamePasswordAuthenticationToken,也就是一个凭证Authentication,这个Authentication只包含了用户名、密码这些基础信息,没有权限等其他信息,然后Authentication作为参数被传到AuthenticationManager接口的实现类ProviderManager类authenticate方法进行认证,ProviderManager类中有一个List<AuthenticationProvider> 列表AuthenticationProvider是接口,AbstractUserDetailsAuthenticationProvider是接口的抽象类,DaoAuthenticationProvider是实现类),该列表存放着不同的登录逻辑AuthenticationProvider,通过for循环去遍历该列表,信息验证的逻辑都是在AuthenticationProvider里面,会依次使用每一AuthenticationProvider进行认证,如果有一个 AuthenticationProvider 认证后的结果不为 null,则表示该AuthenticationProvider已经认证成功,之后的 AuthenticationProvider 将不再继续认证。然后直接以该 AuthenticationProvider 的认证结果作为 ProviderManager 的认证结果。如果所有的 AuthenticationProvider 的认证结果都为 null,则表示认证失败,将抛出一个 ProviderNotFoundException。

DaoAuthenticationProvider内部的认证逻辑:它有一个retrieveUser方法,该方法调用UserDetailsService().loadUserByUsername从数据库获取用户信息,并返回一个UserDetails类型的对象,它含有用户的详细信息,如用户权限等等,然后将UserDetails对象和Authentication校验,成功后会把UserDetails中的信息填入到Authentication,一个最终的Authentication就产生了,它会被保存到安全上下文中!

相关文章:

一文入门SpringSecurity 5

目录 提示 Apache Shiro和Spring Security 认证和授权 RBAC Demo 环境 Controller 引入Spring Security 初探Security原理 认证授权图示​编辑 图中涉及的类和接口 流程总结 提示 Spring Security源码的接口名和方法名都很长&#xff0c;看源码的时候要见名知意&am…...

IPython的HTML魔法:%%html_header命令全解析

IPython的HTML魔法&#xff1a;%%html_header命令全解析 在IPython和Jupyter Notebook中&#xff0c;%%html_header是一个魔术命令&#xff0c;它允许用户在Notebook的单元格中添加HTML头部&#xff08;head&#xff09;内容。这个功能特别有用&#xff0c;当你需要定制Notebo…...

将SQL中的占位符替换成参数

将SQL中的占位符替换成参数 描述 描述 此方法是将SQL中的${}或#{}替换为直接拼接到SQL中或直接替换为?的形式。具体详情看下面代码。 import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern;/*** author HuYu* date 2023-09-21* since 1.0**…...

锁相环 vivado FPGA

原理 同步状态/跟踪状态&#xff1a;相位差在2kπ附近&#xff0c;频率差为0到达上述状态的过程称为捕获过程锁相环的捕获带&#xff1a;delta w的最大值&#xff0c;大于这个值的话就不能捕获鉴相器&#xff08;PD-phase discriminator&#xff09;&#xff1a;相乘加LPF&…...

英语科技写作 希拉里·格拉斯曼-蒂(英文版)pdf下载

下载链接&#xff1a; 链接1&#xff1a;https://pan.baidu.com 链接2&#xff1a;/s/1fxRUGnlJrKEzQVF6k1GmBA 提取码&#xff1a;b69t 由于是英文版&#xff0c;可能有些看着不太方便&#xff0c;可以在网页版使用以下软件中英文对照着看&#xff0c;看着更舒服&#xff0c;…...

《Dynamic Statistical Learning in Massive Datastreams》论文阅读笔记

论文地址: https://www3.stat.sinica.edu.tw/ss_newpaper/SS-2023-0195_na.pdf 论文题目翻译&#xff1a;《在大规模数据流中的动态统计学习》 核心观点&#xff1a; 动态跟踪和筛选框架&#xff08;DTS&#xff09;&#xff1a;论文提出了一个在线学习和模型更新的新框架&…...

【数据分享】2008-2022年我国省市县三级的逐日NO2数据(excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2022年的省市县三级的逐日PM2.5数据、2013-2022年的省市县三级的逐日CO数据和2013-2022年的省市县三级的逐日SO2数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次…...

JavaEE (1)

web开发概述 所谓web开发,指的是从网页中向后端程序发送请求,与后端程序进行 交互. 流程图如下 Web服务器是指驻留于因特网上某种类型计算机的程序. 可以向浏览器等Web客户端提供文档&#xff0c;也可以放置网站文件&#xff0c;让全世界浏览&#xff1b; 它是一个容器&…...

事务、函数和索引

什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 特点 一个事务中如果有一个数据库操作失败&#xff0c;那么整个事务…...

Android APP 基于RecyclerView框架工程(知识体系积累)

说明&#xff1a;这个简单的基于RecyclerView的框架作用在于自己可以将平时积累的一些有效demo整合起来&#xff08;比如音视频编解码的、opengles的以及其他也去方向的、随着项目增多&#xff0c;工程量的增加&#xff0c;后期想高效的分析和查找并不容易&#xff09;&#xf…...

【iOS】GCD

参考文章&#xff1a;GCD函数和队列原理探索 之前写项目的时候&#xff0c;进行耗时的网络请求使用GCD处理过异步请求&#xff0c;但对一些概念都很模糊&#xff0c;这次就来系统学习一下GCD相关 相关概念 什么是GCD&#xff1f; Grand Center Dispatch简称GCD&#xff0c;是…...

C语言 | Leetcode C语言题解之第282题给表达式添加运算符

题目&#xff1a; 题解&#xff1a; #define MAX_COUNT 10000 // 解的个数足够大 #define NUM_COUNT 100 // 操作数的个数足够大 long long num[NUM_COUNT] {0};long long calc(char *a) { // 计算表达式a的值// 将数字和符号&#xff0c;入栈memset(num, 0, sizeof(num));in…...

如何使用 API list 极狐GitLab 容器镜像仓库中的 tag?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…...

粒子群算法PSO优化BP神经网络(PSO-BP)回归预测——Python和MATLAB实现

下面是一个使用Python实现的粒子群算法&#xff08;PSO&#xff09;优化反向传播神经网络&#xff08;BP&#xff09;的示例代码。 以下是具体的代码实现&#xff1a; python import numpy as np from sklearn.datasets import make_regression from sklearn.model_selection…...

React-router路由配置及跳转

1、V6对比V5的修改内容 1、API: useNavigate 代替了useHistory 。 2、废弃了Route组件的exact属性。 3、组件 <Routes>代替了<Switch> 4、组件NavLink中移除了 activeStyle activeClassName 属性。 2、安装依赖react-router-dom npm install react-router-dom…...

vue3【实战】可编辑的脱敏信息

<script lang"ts" setup> import { ref, onMounted } from "vue"; let real_name ref("朝阳");let name ref("");onMounted(() > {name.value des_name(real_name.value); });function focusing() {name.value real_name…...

S71200 - 笔记

1 S71200 0 ProfiNet - 2 PLC编程 01.如何零基础快速上手S7-1200_哔哩哔哩_bilibili 西门子S7-1200PLC编程设计学习视频&#xff0c;从入门开始讲解_哔哩哔哩_bilibili...

linux系统查历史cpu使用数据(使用sar 查询cpu和网络占用最近1个月历史数据)。

一 sar 指令介绍 在 Linux 系统中&#xff0c;sar 是 System Activity Reporter 的缩写&#xff0c;是一个用于收集、报告和保存系统活动信息的工具。它是 sysstat 软件包的一部分&#xff0c;提供了丰富的系统性能数据&#xff0c;包括 CPU、内存、网络、磁盘等使用情况&am…...

Edge浏览器加载ActiveX控件

背景介绍 新版Edge浏览器也是采用Chromium内核&#xff0c;虽然没有谷歌浏览器市场占有率高&#xff0c;但是依托微软操作系统的优势&#xff0c;Edge浏览器还是发展很强劲&#xff0c;占据着市场第二的位置。随着微软停止服务IE浏览器&#xff0c;曾经风光无限的IE浏览器页退出…...

BUG与测试用例设计

一.软件测试的生命周期 需求分析→测试计划→测试设计,测试开发→测试执行→测试评估→上线→运行维护 二.BUG 1.bug的概念 (1)当且仅当规格说明(需求文档)是存在的并且正确,程序与规格说明之间的不匹配才是错误. (2)当需求规格说明书没有提到的功能,判断标准以最终用户为准…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言&#xff1a;生成式AI的黎明 – Diffusion模型是什么&#xff1f; 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;领域取得了爆炸性的进展&#xff0c;模型能够根据简单的文本提示创作出逼真的图像、连贯的文本&#xff0c;乃至更多令人惊叹的…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...