Spring Boot 整合SpringSecurity和JWT和Redis实现统一鉴权认证

📑前言

本文主要讲了Spring Security文章,如果有什么需要改进的地方还请大佬指出⛺️

🎬作者简介:大家好,我是青衿🥇
☁️博客首页:CSDN主页放风讲故事
🌄每日一句:努力一点,优秀一点

在这里插入图片描述

目录

文章目录

  • 📑前言
  • **目录**
    • 一、介绍
    • 二、主要功能
    • 三、原理
      • 1. SpringSecurity 过滤器链
      • 2. JWT校验登录的校验流程
    • 四、Spring Boot整合Redis、SpringSecurity、JWT的示例demo
  • 📑文章末尾


Spring Security

一、介绍

Spring Security是一个强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的实际标准。Spring Security是一个可以为Java应用程序提供全面安全服务的框架。同时,它也可以轻松扩展以满足自定义需求。

二、主要功能

Authentication (认证),就是用户登录
Authorization (授权):一旦身份验证成功,判断用户拥有什么权限,可以访问什么资源
防止跨站请求伪造(CSRF):Spring Security提供了内置的防护机制,可以防止跨站请求伪造攻击。
密码存储:Spring Security提供了多种密码存储格式,包括明文、加密和哈希。
集成其他安全框架:Spring Security可以与其他安全框架如OAuth2、JWT等进行集成,以提供更全面的安全解决方案。

三、原理

​ SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。

1. SpringSecurity 过滤器链

在这里插入图片描述

SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。

  • SecurityContextPersistenceFilter:每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中。
  • LogoutFilter:用于处理退出登录。
  • UsernamePasswordAuthenticationFilter:用于处理基于表单的登录请求,从表单中获取用户名和密码。
  • BasicAuthenticationFilter:检测和处理 http basic 认证。
  • ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException 。
  • FilterSecurityInterceptor:负责权限校验的过滤器,可以看做过滤器链的出口。

流程说明:客户端发起一个请求,进入 Security 过滤器链。
1.当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到logoutSuccessHandler 登出成功处理,如果登出失败则由 ExceptionTranslationFilter ;如果不是登出路径则直接进入下一个过滤器。

2.当到 UsernamePasswordAuthenticationFilter 的时候判断是否为登录路径,如果是,则进入该过滤器进行登录操作,如果登录失败则到 AuthenticationFailureHandler 登录失败处理器处理,如果登录成功则到 AuthenticationSuccessHandler 登录成功处理器处理,如果不是登录请求则不进入该过滤器。

3.当到 FilterSecurityInterceptor 的时候会拿到 uri ,根据 uri 去找对应的鉴权管理器,鉴权管理器做鉴权工作,鉴权成功则到 Controller 层否则到 AccessDeniedHandler 鉴权失败处理器处理。

2. JWT校验登录的校验流程

在这里插入图片描述

首先前端一样是把登录信息发送给后端,后端查询数据库校验用户的账号和密码是否正确,正确的话则使用jwt生成token,并且返回给前端。以后前端每次请求时,都需要携带token,后端获取token后,使用jwt进行验证用户的token是否无效或过期,验证成功后才去做相应的逻辑。

四、Spring Boot整合Redis、SpringSecurity、JWT的示例demo

  1. 添加依赖项在 pom.xml 文件中添加以下依赖项:
   <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
</dependencies>`
  1. 创建Redis配置类
@Configuration
public class RedisConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private int port;@Beanpublic JedisConnectionFactory jedisConnectionFactory() {return new JedisConnectionFactory(new RedisStandaloneConfiguration(host, port));}@Beanpublic RedisTemplate<String, Object> redisTemplate() {final RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(jedisConnectionFactory());return template;}
}
  1. 创建 JwtTokenUtil 类,用于生成和验证JWT令牌。
@Component
public class JwtTokenUtil implements Serializable {private static final long serialVersionUID = -2550185165626007488L;private static final String secret = "mySecret";public String getUsernameFromToken(String token) {return getClaimFromToken(token, Claims::getSubject);}public Date getExpirationDateFromToken(String token) {return getClaimFromToken(token, Claims::getExpiration);}public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {final Claims claims = getAllClaimsFromToken(token);return claimsResolver.apply(claims);}private Claims getAllClaimsFromToken(String token) {return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();}private Boolean isTokenExpired(String token) {final Date expiration = getExpirationDateFromToken(token);return expiration.before(new Date());}public String generateToken(UserDetails userDetails) {Map<String, Object> claims = new HashMap<>();return doGenerateToken(claims, userDetails.getUsername());}private String doGenerateToken(Map<String, Object> claims, String subject) {return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + 5 * 60 * 60 * 1000)).signWith(SignatureAlgorithm.HS512, secret).compact();}public Boolean validateToken(String token, UserDetails userDetails) {final String username = getUsernameFromToken(token);return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));}
}` 
  1. 创建 JwtAuthenticationEntryPoint 类,用于处理未经授权的请求。
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {private static final long serialVersionUID = -7858869558953243875L;@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException {response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");}
}` 
  1. 创建 JwtRequestFilter 类,用于解析和验证JWT令牌。
@Component
public class JwtRequestFilter extends OncePerRequestFilter {@Autowiredprivate MyUserDetailsService myUserDetailsService;@Autowiredprivate JwtTokenUtil jwtTokenUtil;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {final String requestTokenHeader = request.getHeader("Authorization");String username = null;String jwtToken = null;if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {jwtToken = requestTokenHeader.substring(7);try {username = jwtTokenUtil.getUsernameFromToken(jwtToken);} catch (IllegalArgumentException e) {System.out.println("Unable to get JWT Token");} catch (ExpiredJwtException e) {System.out.println("JWT Token has expired");}} else {logger.warn("JWT Token does not begin with Bearer String");}if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = this.myUserDetailsService.loadUserByUsername(username);if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);}}chain.doFilter(request, response);}
}` 
  1. 配置Spring Security
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;@Autowiredprivate UserDetailsService jwtUserDetailsService;@Autowiredprivate JwtRequestFilter jwtRequestFilter;@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll().anyRequest().authenticated().and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);}
}`

以上是简单的Spring Boot整合Redis、Security、JWT和Redis的示例,可以根据自己的实际需求进行调整。

📑文章末尾

在这里插入图片描述

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

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

相关文章

多功能声学综合馆:空间的“膜法师”

建筑是文明的承载者&#xff0c;是历史的见证者&#xff0c;也是城市的象征。但在现代都市中&#xff0c;我们不仅需要“固定”的建筑&#xff0c;更需要灵活与多功能性的空间。而这&#xff0c;正是多功能声学综合馆为我们带来的“膜法”。 不仅仅是建筑&#xff0c;更是艺术的…

【技术干货】开源库 Com.Gitusme.Net.Extensiones.Core 的使用

目录 1、项目介绍 2、为项目添加依赖 3、代码中导入命名空间 4、代码中使用 示例 1&#xff1a;string转换 示例 2&#xff1a;object转换 1、项目介绍 Com.Gitusme.Net.Extensiones.Core是一个.Net扩展库。当前最新版本1.0.4&#xff0c;提供了常见类型转换&#xff0c…

Amazon EC2 安全可调用的云虚拟主机服务器

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Amazon EC2 打造全新的科技链 Amazon Elastic Compute Cloud&#xff08;Amazon EC2&#xff09;提供最广泛、最深入的计算平台&#xff0c;拥有超过 500 个实例&…

服务器经常被攻击的原因

很多中小型企业都是选择虚拟主机服务器&#xff0c;是把一个服务器分成很多个给很多企业一起共用&#xff0c;可能同一个 IP服务器上就有很多个不同企业的网站&#xff0c;这个时候如果跟你同一个IP服务器的网站遭到DDoS攻击&#xff0c;就很有可能会影响到你的网站也无法正常访…

Java中各个版本JDK分别有哪些常见的垃圾回收算法?它们的适用场景和开启方法是什么?

Java中各个版本JDK分别有哪些常见的垃圾回收算法&#xff1f;它们的使用场景和开启方法是什么&#xff1f; 1.1 JDK 1.8 中的垃圾回收算法1.2 JDK 11 中的垃圾回收算法1.3 JDK17中的垃圾回收算法 1.1 JDK 1.8 中的垃圾回收算法 Java 8引入了一些不同类型的垃圾回收算法&#x…

nginx配置支持PHP

前言 Nginx是通过php-fpm来通信的&#xff0c;所以需要修改的监听9000端口。 当 Nginx 配置支持 PHP 时&#xff0c;它可以将 PHP 请求转发给 PHP-FPM&#xff0c;由 PHP-FPM 处理请求并返回结果。 要配置 Nginx 支持 PHP&#xff0c;你需要在 Nginx 配置文件中添加一个 locat…

awk精确筛选

awk精确筛选: $(><):用于对比数值 $n~"字符串"代表第n个字段包括某个字符 $n!~"字符串"代表第n个字段不包括某个字符 $n"字符串"代表第n个字段为某个字符 $n!"字符串"代表第n个字段不为某个字符 $NF:最后一个字段 awk -F…

044_第三代软件开发-保存PDF

第三代软件开发-保存PDF 文章目录 第三代软件开发-保存PDF项目介绍保存PDF头文件源文件使用 关键字&#xff1a; Qt、 Qml、 pdf、 painter、 打印 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object Language&#xff…

【Windows-软件-FFmpeg】(01)通过CMD运行FFmpeg进行操作,快速上手

前言 通过"cmd"运行"ffmpeg"进行操作&#xff0c;快速上手&#xff1b; 实操 【实操一】 说明 使用"ffmpeg"来合并音频文件和视频文件 &#xff1b; 环境 Windows 11 专业版&#xff08;22621.2428&#xff09;&#xff1b; 代码 &#xf…

Java 性能优化之直接使用成员变量 VS 拷贝副本

背景 刷到一个大佬的 CSDN 博客&#xff0c;仔细看了一下性能优化专栏。联想到我们的日常开发工作&#xff0c;由于业务比较简单&#xff0c;很容就忽略性能问题。但是&#xff0c;性能优化的一下常见思路&#xff0c;也早有耳闻。看了一个 Java 性能优化的方法 「减少操作指令…

Linux进程的优先级

Linux进程的优先级 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容讲解Linux中进程的优先级&#xff0…

安防监控系统EasyCVR视频汇聚平台,如何实现视频汇聚?

关注我们的朋友都知道&#xff0c;EasyCVR平台最初就是以汇聚为核心而进行打造的&#xff0c;那到底什么是汇聚平台呢&#xff1f;又如何进行视频资源汇聚&#xff1f;简单来说&#xff0c;视频汇聚平台是指能够从不同的视频源&#xff08;例如直播、点播等&#xff09;收集、整…

Nginx篇---第二篇

系列文章目录 文章目录 系列文章目录一、请列举Nginx和Apache 之间的不同点二、在Nginx中,如何使用未定义的服务器名称来阻止处理请求?三、请解释Nginx服务器上的Master和Worker进程分别是什么?一、请列举Nginx和Apache 之间的不同点 二、在Nginx中,如何使用未定义的服务器…

[移动通讯]【Carrier Aggregation-13】【Carrier Aggregation】

前言&#xff1a; 前面分享过不同note CA 技术文档 这里主要参考 4G|ShareTechnote 《Carrier Aggregation》 CA SCell 添加的小区的流程&#xff1a; SCell addition and removal&#xff1a; 1 The carrier aggregation additional SCells cannot be activated immediately…

pom.xml详解

我们在开发Java应用程序时&#xff0c;pom.xml文件是项目中的核心配置文件之一&#xff0c;它结合Maven实现对项目依赖的拉取&#xff0c;今天就详细了解一下pom.xml文件的配置 Maven是一种构建工具&#xff0c;它用于构建、管理和发布Java项目pom.xml文件包含了项目的所有重要…

已经不做程序媛4年半了,后悔么?不好说...但再次看到之前写的博客,真的感慨万分。

四年半前&#xff0c;我还在大四实习&#xff0c;做了一年Java开发。四年半后&#xff0c;我是地理信息行业的一名销售经理。 今天&#xff0c;突然点开了CSDN&#xff0c;看到自己的博客有很多人看过&#xff0c;霎时间感慨万千…因为上一次这么认真的对待自己&#xff0c;竟…

Python小试牛刀:GUI(图形界面)实现计算器UI界面(三)

上一篇&#xff1a;Python小试牛刀&#xff1a;GUI&#xff08;图形界面&#xff09;实现计算器UI界面(二)-CSDN博客 回顾前两篇文章&#xff0c;第一篇文章主要实现了计算器UI界面如何布局&#xff0c;以及简单概述Python常用的GUI库。第二篇文章主要实现了计算器UI界面按钮组…

<Vue>使用依赖注入的方式共享数据

什么是vue依赖注入&#xff1f; Vue是一个用于构建用户界面的渐进式框架。 它提供了一种简单而灵活的方式来管理组件之间的数据流&#xff0c;即依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;。 依赖注入是一种设计模式&#xff0c;它允许一个组件从另一…

腾讯云CVM服务器标准型S5、SA3、S6详细介绍

腾讯云CVM服务器标准型实例的各项性能参数平衡&#xff0c;标准型云服务器适用于大多数常规业务&#xff0c;例如&#xff1a;web网站及中间件等&#xff0c;常见的标准型云服务器有CVM标准型S5、S6、SA3、SR1、S5se等规格&#xff0c;腾讯云服务器网txyfwq.com来详细说下云服务…

Synchronized与锁升级

一&#xff1a;java对象内存布局 对象在堆内存的存储布局可以划分为三个部分&#xff1a;对象头&#xff08;Header&#xff09;、实例数据&#xff08;Instance Data&#xff09; 和对齐填充 二&#xff1a;对象在堆内存中的存储布局 1&#xff1a;对象头 &#xff08;在64…