Springboot SecurityFilterChain中SPEL抛出IllegalArgumentException问题排查求助
问题描述
当Spring Boot应用接收身份服务器生成的用户令牌请求时,SecurityFilterChain Bean中抛出如下异常:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception java.lang.IllegalArgumentException: Failed to evaluate expression 'authentication.getPrincipal().getSubject() == #userId'
对应的SecurityFilterChain代码片段:
.requestMatchers("/**/user/{userId}/**").access( new WebExpressionAuthorizationManager( "authentication.getPrincipal().getSubject() == #userId" ) )
该异常仅在生产环境出现,过滤器链中调试难度大,使用版本:Spring Boot 3.1.1、Java 17、Spring Security 6.0.3。
可能的问题分析
- Principal类型不匹配:生产环境中
authentication.getPrincipal()返回的对象可能并非预期的OAuth2认证对象,比如是String类型的用户名,而非包含getSubject()方法的OAuth2Principal。开发环境因测试配置/数据,Principal是完整认证对象,但生产环境令牌解析后可能仅保留用户名,调用getSubject()时触发异常,导致SPEL表达式求值失败。 - 路径变量绑定失败:生产环境请求路径格式异常,或Spring Security未正确将路径中的
{userId}解析为SPEL变量#userId,导致表达式中#userId为null,与getSubject()返回值比较时触发求值异常。 - 缺乏空安全处理:表达式未做空安全校验,若
authentication、authentication.getPrincipal()为null,或getSubject()返回null,都会直接导致表达式求值失败。生产环境可能存在未认证请求意外进入该过滤器链的情况,而开发环境有前置拦截器拦截了这类请求,因此未触发问题。 - 类型隐式转换失败:
getSubject()返回字符串类型,而#userId可能被解析为数值类型(比如路径中userId是数字),直接用==比较会触发类型不匹配的求值异常。开发环境userId多为字符串格式或隐式转换成功,但生产环境路径变量类型解析逻辑不同导致失败。
内容的提问来源于stack exchange,提问作者heikorm
相关产品推荐
相关产品推荐

