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

SpringBoot3配置SpringSecurity6

访问1:localhost:8080/security,返回:需要先认证才能访问(说明没有权限)

访问2:localhost:8080/anonymous,返回:anonymous(说明正常访问)


 

相关文件如下:

pom.xml:

   <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.4</version><relativePath/> <!-- lookup parent from repository --></parent><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.18</version></dependency>

 WebSecurityConfiguration:

/*** Spring Security 配置项*/
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@EnableGlobalAuthentication
public class WebSecurityConfiguration {@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;@Autowiredprivate RestAuthenticationEntryPoint restAuthenticationEntryPoint;@Autowiredprivate RestAccessDeniedHandler restAccessDeniedHandler;private UserDetailsService userDetailsService;@Autowiredprivate ApplicationContext applicationContext;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {// 搜寻 匿名标记 url: PreAuthorize("hasAnyRole('anonymous')") 和 PreAuthorize("@tsp.check('anonymous')") 和 AnonymousAccessMap<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();Set<String> anonymousUrls = new HashSet<>();for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {HandlerMethod handlerMethod = infoEntry.getValue();AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);PathPatternsRequestCondition pathPatternsCondition = infoEntry.getKey().getPathPatternsCondition();Set<String> patternList = new HashSet<>();if (null != pathPatternsCondition){Set<PathPattern> patterns = pathPatternsCondition.getPatterns();for (PathPattern pattern : patterns) {patternList.add(pattern.getPatternString());}}if (null != preAuthorize && preAuthorize.value().toLowerCase().contains("anonymous")) {anonymousUrls.addAll(patternList);} else if (null != anonymousAccess && null == preAuthorize) {anonymousUrls.addAll(patternList);}}httpSecurity// 禁用basic明文验证.httpBasic(it -> it.disable())// 前后端分离架构不需要csrf保护.csrf(it -> it.disable())// 禁用默认登录页.formLogin(it -> it.disable())// 禁用默认登出页.logout(it -> it.disable())// 设置异常的EntryPoint,如果不设置,默认使用Http403ForbiddenEntryPoint.exceptionHandling(exceptions -> {// 401exceptions.authenticationEntryPoint(restAuthenticationEntryPoint);// 403exceptions.accessDeniedHandler(restAccessDeniedHandler);})// 前后端分离是无状态的,不需要session了,直接禁用。.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests// 允许匿名访问.requestMatchers(anonymousUrls.toArray(new String[0])).permitAll()// 允许所有OPTIONS请求.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()// 允许 SpringMVC 的默认错误地址匿名访问.requestMatchers("/error").permitAll()// 允许任意请求被已登录用户访问,不检查Authority.anyRequest().authenticated()).authenticationProvider(authenticationProvider())// 加我们自定义的过滤器,替代UsernamePasswordAuthenticationFilter.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);return httpSecurity.build();}@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration config = new CorsConfiguration();// 允许所有域名进行跨域调用config.addAllowedOrigin("*");// 放行全部原始头信息config.addAllowedHeader("*");// 允许所有请求方法跨域调用config.addAllowedMethod("OPTIONS");config.addAllowedMethod("GET");config.addAllowedMethod("POST");config.addAllowedMethod("PUT");config.addAllowedMethod("DELETE");source.registerCorsConfiguration("/**", config);return new CorsFilter(source);}@Beanpublic UserDetailsService userDetailsService() {return username -> userDetailsService.loadUserByUsername(username);}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic AuthenticationProvider authenticationProvider() {DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();authProvider.setUserDetailsService(userDetailsService());// 设置密码编辑器authProvider.setPasswordEncoder(passwordEncoder());return authProvider;}}

JwtAuthenticationTokenFilter
/*** JWT登录授权过滤器*/@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,@NonNull FilterChain chain) throws ServletException, IOException {String authorization = request.getHeader("Authorization");response.setCharacterEncoding("utf-8");if (null == authorization){// 没有tokenchain.doFilter(request, response);return;}try{if (!authorization.startsWith("Bearer ")){// token格式不正确response.sendError(HttpServletResponse.SC_BAD_REQUEST, "token格式不正确");return;}boolean verify = MyJWTUtil.verify(authorization);if(!verify){// token格式不正确response.sendError(HttpServletResponse.SC_BAD_REQUEST, "token验证失败");return;}}catch (Exception e){// token格式不正确response.sendError(HttpServletResponse.SC_BAD_REQUEST, "token验证失败");return;}JWT jwt = MyJWTUtil.parseToken(authorization);Object uid = jwt.getPayload("uid");// todo 解析JWT获取用户信息LoginUser loginUser = new LoginUser();UsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken(loginUser,null,null);SecurityContextHolder.getContext().setAuthentication(authenticationToken);chain.doFilter(request, response);}}
RestAuthenticationEntryPoint:
/*** 认证失败处理类*/@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException {response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Cache-Control", "no-cache");response.setContentType("application/json");response.setCharacterEncoding("UTF-8");response.setStatus(HttpStatus.UNAUTHORIZED.value());response.getWriter().println(authException == null? "Unauthorized" : "需要先认证才能访问");response.getWriter().flush();}}
RestAccessDeniedHandler:
/*** 自定义无权访问处理类*/
@Component
public class RestAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response,AccessDeniedException accessDeniedException) throws IOException {response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Cache-Control", "no-cache");response.setContentType("application/json");response.setCharacterEncoding("UTF-8");response.setStatus(HttpStatus.FORBIDDEN.value());
//        response.getWriter()
//                .println(accessDeniedException==null?"AccessDenied":accessDeniedException.getMessage());response.getWriter().println(accessDeniedException == null? "AccessDenied" : "没有访问权限");response.getWriter().flush();}}
AnonymousAccess:
/*** 用于标记匿名访问方法*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnonymousAccess {}
MyJWTUtil:
/*** JWT工具类*/
public class MyJWTUtil extends JWTUtil {/*** 解析JWT Token** @param token token* @return {@link JWT}*/public static boolean verify(String token) {return verify(token, "LOGIN_TOKEN_KEY_20240410".getBytes());}/*** 解析JWT Token** @param token token* @return {@link JWT}*/public static boolean verify(String token, byte[] key) {if(StrUtil.isNotEmpty(token)){if(token.startsWith("Bearer ")){token = token.split("Bearer ")[1].trim();}}return JWT.of(token).setKey(key).verify();}/*** 解析JWT Token** @param token token* @return {@link JWT}*/public static JWT parseToken(String token) {if(StrUtil.isNotEmpty(token)){if(token.startsWith("Bearer ")){token = token.split("Bearer ")[1].trim();}}return JWT.of(token);}public static String getToken(HttpServletRequest request) {final String requestHeader = request.getHeader("Authorization");if (requestHeader != null && requestHeader.startsWith("Bearer ")) {return requestHeader.substring(7);}return null;}public static String createToken(String userId) {Map<String, Object> payload = new HashMap<>(4);payload.put("uid", userId);payload.put("expire_time", System.currentTimeMillis() + 1000 * 60 * 60 * 8);return createToken(payload, "LOGIN_TOKEN_KEY_20240410".getBytes());}
}

DemoController:
@RestController
public class DemoController {@GetMapping("anonymous")@AnonymousAccesspublic String loadCondition() {return "anonymous";}@GetMapping("security")public String security() {return "security";}}

相关文章:

SpringBoot3配置SpringSecurity6

访问1&#xff1a;localhost:8080/security&#xff0c;返回&#xff1a;需要先认证才能访问&#xff08;说明没有权限&#xff09; 访问2&#xff1a;localhost:8080/anonymous&#xff0c;返回&#xff1a;anonymous&#xff08;说明正常访问&#xff09; 相关文件如下&…...

Unity之Unity面试题(三)

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之Unity面试题&#xff08;三&#xff09; TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取…...

Linux命令-dos2unix命令(将DOS格式文本文件转换成Unix格式)

说明 dos2unix命令 用来将DOS格式的文本文件转换成UNIX格式的&#xff08;DOS/MAC to UNIX text file format converter&#xff09;。DOS下的文本文件是以 \r\n 作为断行标志的&#xff0c;表示成十六进制就是0D0A。而Unix下的文本文件是以\n作为断行标志的&#xff0c;表示成…...

企业怎么做数据分析

数据分析在当今信息化时代扮演着至关重要的角色。能够准确地收集、分析和利用数据&#xff0c;对企业的决策和发展都具有重要意义。数聚将介绍企业如何合理地利用数据分析&#xff0c;如何协助企业在竞争激烈的市场中取得优势。 一、建立完善的数据收集系统 在进行数据分析之…...

1111111111

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…...

[面向对象] 单例模式与工厂模式

单例模式 是一种创建模式&#xff0c;保证一个类只有一个实例&#xff0c;且提供访问实例的全局节点。 工厂模式 面向对象其中的三大原则&#xff1a; 单一职责&#xff1a;一个类只有一个职责&#xff08;Game类负责什么时候创建英雄机&#xff0c;而不需要知道创建英雄机要…...

《前端防坑》- JS基础 - 你觉得typeof nullValue === null 么?

问题 JS原始类型有6种Undefined, Null, Number, String, Boolean, Symbol共6种。 在对原始类型使用typeof进行判断时, typeof stringValue string typeof numberValue number 如果一个变量(nullValue)的值为null&#xff0c;那么typeof nullValue "?" const u …...

【项目实战经验】DataKit迁移MySQL到openGauss(下)

上一篇我们分享了安装、设置、链接、启动等步骤&#xff0c;本篇我们将继续分享迁移、启动~ 目录 9. 离线迁移 9.1. 迁移插件安装 中断安装&#xff0c;比如 kill 掉java进程&#xff08;安装失败也要等待300s&#xff09; 下载安装包准备上传 缺少mysqlclient lib包 mysq…...

AI预测体彩排3第2弹【2024年4月13日预测--第1套算法开始计算第2次测试】

各位小伙伴&#xff0c;今天实在抱歉&#xff0c;周末回了趟老家&#xff0c;回来比较晚了&#xff0c;数据今天上午跑完后就回老家了&#xff0c;晚上8点多才回来&#xff0c;赶紧把预测结果发出来吧&#xff0c;虽然有点晚了&#xff0c;但是咱们前面说过了&#xff0c;目前的…...

【13137】质量管理(一)2024年4月串讲题组一

目录 1.选择题 2.多选题 3.简答题 4.论述题 5.计算题 6.论述题 【13137】质量管理-速 记 宝 典【全国通用】</...

Go语言中工作负载类型对并发的影响

在实际工作开发中我们需要根据工作负载是CPU密集型还是I/O密集型,使用不同的方式来解决问题。下面我们先来看这些概念,然后再讨论其影响。 在程序执行时,工作负载的执行时间会受以下因素限制: CPU的速度--例如,运行归并排序算法。工作负载被称为CPU密集型。I/O速度--例如…...

常用的Python内置函数

目录 1. getattr() 函数: 2. setattr() 函数: 3. id():返回对象的唯一标识符(内存地址)。 4. type():返回对象的类型。 5. isinstance(obj, classinfo):判断对象是否是某种类型或其子类的实例。 6. issubclass(class1, class2):判断一个类是否是另一个类的子类。 …...

MAC(M1芯片)编译Java项目慢且发热严重问题解决方案

目录 一、背景二、排查三、解决四、效果以及结果展示五、总结 一、背景 使用idea编译项目等操作&#xff0c;经常性发热严重&#xff0c;并且时间慢。直到昨天编译一个项目用时30分钟&#xff0c;电脑温度很高&#xff0c;并且有烧灼的味道&#xff0c;于是有了此篇文章。 二、…...

如何循环pandas格式的数据

如何循环pandas格式的数据 要循环处理 Pandas 格式的数据&#xff0c;可以使用 iterrows() 方法或者 iteritems() 方法。 iterrows() 方法&#xff1a; import pandas as pd# 假设 df 是你的 Pandas DataFrame for index, row in df.iterrows():# 在这里处理每一行的数据&am…...

新零售SaaS架构:客户管理系统架构设计(万字图文总结)

什么是客户管理系统&#xff1f; 客户管理系统&#xff0c;也称为CRM&#xff08;Customer Relationship Management&#xff09;&#xff0c;主要目标是建立、发展和维护好客户关系。 CRM系统围绕客户全生命周期的管理&#xff0c;吸引和留存客户&#xff0c;实现缩短销售周…...

Apache Spark

Apache Spark是一种开源的分布式计算系统&#xff0c;主要用于大数据处理和分析。Spark提供了一个高效的计算引擎&#xff0c;可以在分布式环境中处理大规模数据集。它支持多种编程语言&#xff0c;包括Scala、Java、Python和R。 Spark的核心概念是弹性分布式数据集&#xff0…...

CentOS7编译ZLMediaKit并使能WebRTC

使能WebRTC需要libsrtp库, libsrtp库需要openssl, 所以第一步先安装openssl, 系统自带的版本是1.0.2的, libsrtp需要1.1.1以上版本, 需要使用源码进行编译; GCC准备 需要安装gcc7以上版本, 并切换到gcc7的编译环境 yum install centos-release-scl yum install devtoolset-7…...

【数据交换格式】网络socket编程温度采集智能存储与上报项目技术------JSON、TLV

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…...

IP地址定位技术在各领域的作用

IP地址定位是通过确定IP地址的物理位置来定位一个设备的技术&#xff0c;它在现代社会的多个领域中都有着广泛的应用。以下将详细探讨IP地址定位的应用场景&#xff0c;以期对读者有所启发。 首先&#xff0c;在网络安全领域&#xff0c;IP地址定位发挥着至关重要的作用。网络…...

代码随想录 538. 把二叉搜索树转换为累加树

题目 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下&#xff0c;二叉搜索树满足下列约束条件&a…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

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

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

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...