SpringSecurity6配置requestMatchers().permitAll() 无效问题

版本

<spring-boot.version>3.0.2</spring-boot.version>
<jjwt.version>0.12.5</jjwt.version>

问题描述

题主在写 SpringSecurity6 + JWT 做登录认证开发。一路跟着教程叭叭的敲。等到接口验证的时候,发现我的登录接口虽然在SecurityConfig中配置了免验证,但是访问登录接口的时候还是被拦截了。

这里先直接点题说明题主出错的原因:
因为我配置的URL是全路径的,也就是携带着server.servlet.context-path的配置内容的,类似这样/bees/API/login/wechat,其中/bees就是我配置的context-path

我出问题的时候已经在网上找了很多解决方式。但是都没有解决我的问题。
当我在访问我的login接口的时候,系统依然进入了我的自定义验证过滤器中。
后面在通义千问中,AI给出的建议,配置Security的日志输出级别到DEBUG这样能有效地排查问题。

logging.level.org.springframework.security=DEBUG

这样将SpringSecurity的log级别调到DEBUG,在启动服务的时候发现了两行有用的日志
在这里插入图片描述
这是在遇到问题,根据各种文章修改完依然没能解决问题之后的唯一一点曙光。

解决:去掉/bees之后,再次请求登录接口,就不会再过我们自定义的认证拦截器了。

这就是题主的遇到的问题症结所在。

总结

三点。

  1. 检查你自定义的认证拦截器是不是交给Spring管理了(如果是可能会有问题)。
  2. 检查你的SecurityConfig配置类中是否有配置WebSecurityCustomizer这个Bean(没有需要加上)。
  3. 最后检查你需要免验证的URL是否跟我一样加了context-path(或者使用了通配符,题主试过通配符但是不太行,可能是我使用方式有问题)。

最后贴一个比较完整的代码片段

包括 SecurityConfig JwtAuthenticationFilter JwtTokenUtil

代码片段如下:

SecurityConfig

@Configuration
@EnableWebSecurity
public class SecurityConfig {@Autowiredprivate JwtTokenUtil jwtTokenUtil;@Autowiredprivate UserServiceImpl userService;@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {//关闭csrf和frameOptions,如果不关闭会影响前端请求接口http.csrf(AbstractHttpConfigurer::disable).headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable));//开启跨域以便前端调用接口http.cors();//这里是配置的关键,决定哪些接口开启防护,哪些接口绕过防护// 配置访问控制规则http.authorizeHttpRequests(request ->// 指定特定接口无需验证即可访问,如微信登录request.requestMatchers(HttpMethod.POST, "/API/login/wechat").permitAll()// 其他所有以 "/bees/" 开头的接口需要认证才能访问.requestMatchers("/bees/**").authenticated());//禁用sessionhttp.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//将我们自定义的认证过滤器替换掉默认的认证过滤器,指定将自定义的Filter添加到某个指定的Filter之前或者之后http.addFilterBefore(new WeChatLoginFilter(jwtTokenUtil, userService), UsernamePasswordAuthenticationFilter.class);//指定认证错误处理器http.exceptionHandling().authenticationEntryPoint(new BeesAuthenticationFailEntryPoint()).accessDeniedHandler(new BeesDeniedHandler());return http.build();}/*** 指定加密器** @return BCryptPasswordEncoder*/@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic AuthenticationProvider authenticationProvider() {DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();// 提供自定义loadUserByUsernameauthProvider.setUserDetailsService(userService);// 指定密码编辑器authProvider.setPasswordEncoder(passwordEncoder());return authProvider;}@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {return config.getAuthenticationManager();}@Beanpublic WebSecurityCustomizer ignoringCustomizer() {return (web) -> web.ignoring().requestMatchers(HttpMethod.POST, "/API/login/wechat");}
}

JwtAuthenticationFilter

/**
* 自定义的认证过滤器不交给Spring管理
*/
public class WeChatLoginFilter extends OncePerRequestFilter {private static final Logger log = LoggerFactory.getLogger(WeChatLoginFilter.class);private final JwtTokenUtil jwtTokenUtil;private final UserServiceImpl userService;public WeChatLoginFilter(JwtTokenUtil jwtTokenUtil, UserServiceImpl userService) {this.jwtTokenUtil = jwtTokenUtil;this.userService = userService;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {log.info("---WeChatLoginFilter---");String authorizationS = request.getHeader("Authorization");if (!StringUtils.hasLength(authorizationS)) {chain.doFilter(request, response);return;}Claims claims = jwtTokenUtil.getAllClaimsFromToken(authorizationS);//说明解析失败了if (claims == null) {throw new BadCredentialsException("token异常或已过期");}String authorization = claims.getSubject();TokenInfo tokenInfo = JSON.parseObject(authorization, TokenInfo.class);//通过loginType的区分,避免每次都查数据库if (LoginType.WX.getLoginType().equals(tokenInfo.getLoginType())) {User user = userService.loadUserByUserId(tokenInfo.getUserId());//用户不存在 todoBeesCommonAuthenticationToken authentication = new BeesCommonAuthenticationToken(JSON.toJSONString(user), "");//UserDetail user = userService.loadUserByUserId(tokenInfo.getUserId());
//                BeesCommonAuthenticationToken authentication = new BeesCommonAuthenticationToken(user.getUser().getWxOpenId(), "", user.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authentication);}chain.doFilter(request, response);}
}

JwtTokenUtil

@Component
public class JwtTokenUtil {private static final long JWT_EXPIRATION_TIME_MS = 86400000; // 1 day/*** 加密用的盐*/@Value("${security.jwt.secretKey}")private String secretKey;// 生成JWT令牌public String generateToken(Integer loginType, Long userId) {TokenInfo tokenInfo = new TokenInfo();tokenInfo.setUserId(userId);tokenInfo.setLoginType(loginType);String subject = JSON.toJSONString(tokenInfo);Map<String, Object> claims = new HashMap<>();return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_TIME_MS)).signWith(getSigningKey(), SignatureAlgorithm.HS256).compact();}// 解析JWT令牌并获取claimspublic Claims getAllClaimsFromToken(String token) {return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();}// 从JWT令牌中提取用户名public String getUsernameFromToken(String token) {return getAllClaimsFromToken(token).getSubject();}// 验证JWT令牌是否有效public Boolean validateToken(String token, UserDetails userDetails) {final String username = getUsernameFromToken(token);return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));}// 检查JWT令牌是否过期private Boolean isTokenExpired(String token) {final Date expiration = getAllClaimsFromToken(token).getExpiration();return expiration.before(new Date());}// 生成签名密钥private SecretKey getSigningKey() {byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8);return Keys.hmacShaKeyFor(keyBytes);}
}

——————————————以上————————————————————
希望对各位有帮助。

参考文章:
SpringSecurity6解决requestMatchers().permitAll()后依然执行自定义过滤器的问题

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

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

相关文章

【Linux】掌握Linux系统编程中的权限与访问控制

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

电源小白入门学习7——USB充电、供电、电源路径管理

电源小白入门学习7——USB充电、供电、电源路径管理 USB充电系统需要考虑的因素开关充电和线性充电充电路径管理输入限流路径管理&#xff08;动态功率管理&#xff09;理想二极管帮助提高电池利用率输入过充抑制 上期我们介绍了锂离子电池的电池特性&#xff0c;及充电电路设计…

QT--1

类型界面 #include "mywidget.h"myWidget::myWidget(QWidget *parent): QWidget(parent) {//窗口相关设置this->resize(680,520);this->setFixedSize(680,520);this->setWindowTitle("Tim");this->setWindowFlag(Qt::FramelessWindowHint);th…

生成一个好故事!StoryDiffusion:一致自注意力和语义运动预测器必不可少(南开字节)

文章链接&#xff1a;https://arxiv.org/pdf/2405.01434 主页&#xff1a;https://storydiffusion.github.io/ 对于最近基于扩散的生成模型来说&#xff0c;在一系列生成的图像中保持一致的内容&#xff0c;尤其是那些包含主题和复杂细节的图像&#xff0c;是一个重大挑战。本…

视频降噪算法 Meshflow 介绍

介绍 Meshflow 视频降噪算法来自于 2017 年电子科技大学一篇高质量论文。 该论文提出了一个新的运动模型MeshFlow&#xff0c;它是一个空间平滑的稀疏运动场 (spatially smooth sparse motion field)&#xff0c;其运动矢量 (motion vectors) 仅在网格顶点 (mesh vertexes) 处…

一般显卡3d建模渲染够用吗?3d云渲染助力

3D建模和渲染对计算机硬件有较高要求&#xff0c;特别是显卡。显卡的性能直接影响渲染速度&#xff0c;低端和高端显卡在渲染效率上存在显著差异。对于追求快速渲染的用户&#xff0c;高端显卡是首选。那么&#xff0c;4050显卡是否能够满足3D建模渲染的需求呢?下面我们来探讨…

[蓝桥杯2024]-PWN:ezheap解析(堆glibc2.31,glibc2.31下的double free)

查看保护 查看ida 大致就是只能创建0x60大小的堆块&#xff0c;并且uaf只能利用一次 完整exp&#xff1a; from pwn import* #context(log_leveldebug) pprocess(./ezheap2.31)def alloc(content):p.sendlineafter(b4.exit,b1)p.send(content) def free(index):p.sendlineaft…

Java-(乘法表之后)增强for循环

这里我们先做个了解&#xff0c;之后我会在数组中进行详细介绍Java5引入了一种主要用于数组或集合的增强型for循环Java增强型for循环语法格式如下 For(声明语句&#xff1a;表达式&#xff09;{ //代码语句 } 声明语句&#xff1a;声明新的局部变量&#xff0c;该变量的类型…

高效转化,智能私信软件策略揭秘

在数字营销的浪潮中&#xff0c;智能私信软件策略正成为提升转化率的重要工具。这种软件以其个性化、自动化的特点&#xff0c;正在重新定义与客户的互动方式&#xff0c;让企业能够更加高效地吸引并留住潜在客户。 智能私信软件的核心在于其高度的定制化和人性化设计。通过大数…

opencv基础篇 ——(十六)图形绘制与填充

OpenCV 提供了丰富的图形绘制和填充功能&#xff0c;主要通过 cv::rectangle, cv::circle, cv::line, cv::polylines, cv::fillPoly 和 cv::ellipse 等函数实现。以下是一些基本的图形绘制和填充操作的说明&#xff1a; 矩形: 函数: cv::rectangle语法: cv::rectangle(img, rec…

【C++】Vector详解

Vector是什么&#xff1f; vector是C&#xff08;STL&#xff09;中的一种序列容器Vector是一个动态数组&#xff0c;内存空间是连续的&#xff0c;支持随机访问&#xff0c;支持迭代器访问 Vector代码实现 变量指向 代码初始化 #include<iostream> using namespace …

mysql优化面试总结

mysql优化 和 mysql优化之索引 两篇文章有大量的实验性的内容&#xff0c;我暂时没时间理解&#xff0c;把八股部分总结到这篇文章中&#xff0c;方便记忆 我们为什么要对sql进行优化 我们开发项目上线初期&#xff0c;由于业务数据量相对较少&#xff0c;一些SQL的执行效率对…

2024年电工杯数学建模竞赛A题B题思路代码分享

您的点赞收藏是我继续更新的最大动力&#xff01; 欲获取更多电工杯学习资料&#xff0c;可点击如下卡片链接 点击链接加入群聊【2024电工杯】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&k_PrjarulWZU8JsAOA9gnj_oHKIjFe195&authKeySbv2XM853pynlnXiv6M58…

景源畅信数字:抖音怎么挂橱窗商品?

抖音作为一款短视频分享平台&#xff0c;近年来逐渐融入了电商功能&#xff0c;其中“橱窗”就是商家或个人展示和销售商品的一个重要工具。如何在抖音上挂橱窗商品&#xff0c;成为了众多商家关注的焦点。 一、确保账号资质&#xff1a;在抖音上挂橱窗商品前&#xff0c;需要确…

会声会影电影片头怎么做 会声会影电影质感调色技巧 会声会影视频制作教程 会声会影下载免费中文版

片头通常通过一系列的图像、音乐和文字等元素来引入电影的主题和氛围。通过视觉和音频的呈现方式&#xff0c;给观众留下深刻的第一印象&#xff0c;为电影的故事铺设基础。这篇文章来学习一下会声会影电影片头怎么做&#xff0c;会声会影电影质感调色技巧。 一、会声会影电影…

AD23中 X-Signal功能在DDR中T型线等长处理的应用

cadence的Auto-interative Delay Tune功能在设置多跟等长线是十分方便的&#xff1a; Allegro Auto-interactive Delay Tune-教育-高清完整正版视频在线观看-优酷 (youku.com) Allegro AIDT DDR3自动等长视频教程Auto-Interactive Delay Tune_哔哩哔哩_bilibili AD中需要先建…

[Java EE] 多线程(八):CAS问题与JUC包

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (90平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

MaxKB宝塔Docker安装并配置域名访问

准备 Linux系统 bt面板 默认环境LNMP随便装 服务器环境配置最好是4G&#xff0c; 占用硬盘存储大概1G 对于一些海外AI产品的对接需要使用香港或者海外的服务器 安装 在宝塔面板中打开SSH或者你本地使用SSH工具去链接服务器 运行docker命令 前提是放开服务器的8080端口 doc…

【吊打面试官系列】Java高并发篇 - Java 线程池中 submit() 和 execute()方法有什么区别?

大家好&#xff0c;我是锋哥。今天分享关于 【Java 线程池中 submit() 和 execute()方法有什么区别&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; Java 线程池中 submit() 和 execute()方法有什么区别&#xff1f; 两个方法都可以向线程池提交任务&#xff0c…

Redis - Zset 有序集合

前言 它保留了集合不能有重复成员的特点&#xff0c;但与集合不同的是&#xff0c;有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数&#xff08;score&#xff09;与之关联&#xff0c;有序集合中的元素是可以维护有序性的&#xff0c;但这个有序不是⽤下标作为排序依据⽽是…