Spring Security 5: UsernamePasswordAuthenticationFilter 的子类重写 unsuccessfulAuthentication 方法不执行分析及解决

一、前言:

在 Spring Security 框架中,最常用的 Filter 便是表单登录Filter,即 UsernamePasswordAuthenticationFilter。从下图中,能清晰的了解到 UsernamePasswordAuthenticationFilter 的继承关系。
在这里插入图片描述最近我用 Spring Security 做登录验证的时候遇到一个问题。UsernamePasswordAuthenticationFilter 继承的子类重写successfulAuthentication 、unsuccessfulAuthentication 后,发现登录成功会调用 successfulAuthentication 方法, 然而登录失败却不会调用 unsuccessfulAuthentication 方法, 而是直接抛出异常:

org.springframework.security.authentication.BadCredentialsException: Bad credentials
在这里插入图片描述


二、部分代码:

UsernamePasswordAuthenticationFilter 的继承子类:认证过滤器,如果用户名和密码正确,那么过滤器将创建一个JWT Token 并在 HTTP Response 的 header 中返回它,格式:token: “Bearer +具体token值”, 反之返回登录失败。

在这里插入图片描述在这里插入图片描述


二、问题分析及解决:

查看 Spring Security 账号密码验证这一块的源码:DaoAuthenticationProvider.java
在这里插入图片描述从上面源码可以看出当用户输入的密码与数据库查询出的密码不匹配时,JVM 会立即终止当前线程的运行,并向上一层(ProviderManager.java)抛出异常。
在这里插入图片描述异常最后会在 ProviderManager.java 类中被抛出:
在这里插入图片描述最终被我的 try {} catch (Exception e) {} 捕获处理,将异常打印到控制台,并且 return null
在这里插入图片描述

程序直接结束了,并没有调用 unsuccessfulAuthentication 方法。我打算跟着正确的账号密码断点走一遍看下最后会在哪里调用 successfulAuthentication 方法,得知在 AbstractAuthenticationProcessingFilter.java 抽象类中被调用,最终执行子类 JwtAuthenticationFilter 重写的 successfulAuthentication 方法。并且发现 unsuccessfulAuthentication 方法就在上面,是通过捕获 InternalAuthenticationServiceException | AuthenticationException 异常来调用执行。
在这里插入图片描述那我就在想,是不是我外层自定义的 try {} catch (Exception e) {} 把异常捕获并 return null,导致异常没有抛到 AbstractAuthenticationProcessingFilter.java 类中去? 我试着去掉 return null, 发现问题得以解决。其实这里并不需要加 try catch 处理异常,这里就是需要异常作为依据,不要去做任何操作!
在这里插入图片描述


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Security执行链是由一系列的过滤器(Filter)组成的。这些过滤器按照特定的顺序来执行,每个过滤器负责不同的安全任务。具体的执行链可以根据Spring Security的配置进行自定义,但是通常情况下,Spring Security默认的执行链包含以下几个过滤器: 1. ChannelProcessingFilter:负责处理安全通道的请求,例如强制使用HTTPS或HTTP。 2. SecurityContextPersistenceFilter:负责在请求之间持久化SecurityContext,以便在后续的请求中进行使用。 3. ConcurrentSessionFilter:用于处理并发会话控制,确保用户在同一时间只能拥有一个活动会话。 4. LogoutFilter:负责处理用户注销请求,并清除相关的认证信息。 5. X509AuthenticationFilter:用于处理基于X.509证书的认证请求。 6. UsernamePasswordAuthenticationFilter:负责处理基于用户名和密码的认证请求。 7. DefaultLoginPageGeneratingFilter:用于自动生成默认的登录页面。 8. DefaultLogoutPageGeneratingFilter:用于自动生成默认的注销页面。 9. BasicAuthenticationFilter:处理基于HTTP基本认证的请求。 10. RequestCacheAwareFilter:用于处理请求缓存,以便在用户成功认证后重新处理之前的请求。 11. SecurityContextHolderAwareRequestFilter:负责包装请求,以提供对SecurityContextHolder的访问。 12. RememberMeAuthenticationFilter:处理基于“记住我”的认证请求。 13. AnonymousAuthenticationFilter:用于处理匿名用户的请求。 14. SessionManagementFilter:处理会话管理相关的任务,例如会话并发控制和会话超时处理。 15. ExceptionTranslationFilter:负责捕获并处理Spring Security抛出的异常。 16. FilterSecurityInterceptor:最后一个过滤器,负责根据配置的访问规则来进行访问控制。 这些过滤器按照顺序依次执行,每个过滤器根据需要进行认证、授权或其他安全相关的操作。通过这样的执行链,Spring Security能够实现灵活的安全管理功能,同时也为开发者提供了扩展和定制的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0rta1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值