You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring MVC迁移Spring Boot时Spring Security XML配置异常问题

Spring Security 迁移配置差异问题解答

1、同配置在Spring MVC与Spring Boot环境下行为不一致的原因

  • 先明确两个配置的底层逻辑:<security:http pattern="xxx" security="none"/> 会生成一条不挂载任何Spring Security过滤器的空安全链,匹配优先级高于普通带鉴权规则的安全链,请求一旦匹配到这条链,所有安全逻辑(鉴权、CSRF校验、会话处理等)会全部跳过;而<intercept-url access="permitAll"/>只是给匹配路径的请求授予匿名访问权限,请求还是会完整走完整个安全过滤器链。
  • 第一重差异是Spring Security版本迭代带来的默认逻辑变更:原项目用的5.6.4版本中,security="none"对应的空安全链的路径匹配器不会判断请求分发类型,只要路径匹配就生效;而Spring Boot 2.7.1依赖的5.7.2版本对齐Servlet规范要求,空安全链默认仅匹配REQUEST类型的外部直接请求,不会匹配FORWARD/INCLUDE/ERROR等服务器内部转发的请求。
  • 第二重差异是过滤器注册逻辑不同:原传统Spring MVC项目在web.xml里手动注册springSecurityFilterChain时,只配置了REQUEST、FORWARD两种分发类型,但受5.6版本空链不区分分发类型的逻辑影响,不管是外部访问登录页的REQUEST请求,还是服务器内部转发到xhtml视图的FORWARD请求,都会被空链匹配,直接跳过所有鉴权逻辑,所以不会报错。而Spring Boot 2.7.x自动注册安全过滤器时,默认支持REQUEST/FORWARD/INCLUDE/ERROR/ASYNC全部分发类型,访问登录页时,第一次外部REQUEST请求确实能匹配上空链放行,但后续服务器内部FORWARD到同个xhtml路径时,因为分发类型是FORWARD,匹配不上仅支持REQUEST的空安全链,就会落到后面的普通安全链上。
  • 落到普通安全链后抛异常的原因也和版本适配有关:5.7版本中,安全链里的默认过滤器默认配置为单次请求仅执行一次,FORWARD类型的请求不会重复经过AnonymousAuthenticationFilter,也就不会被填充匿名认证对象,而FilterSecurityInterceptor在鉴权前会先检查SecurityContext中是否存在Authentication对象,不存在就直接抛出认证信息不存在的异常,根本不会走到permitAll的权限判断逻辑。移除security="none"配置后,所有分发类型的请求都统一走普通安全链,路径匹配逻辑一致,过滤器全链路正常执行,访问就恢复正常了。

2、原配置同时保留两条同路径规则是否存在合理使用场景

  • 结论是绝大多数场景下这就是冗余配置,没有保留必要。
  • 唯一能追溯到的适用场景是Spring Security 3.x到4.1.x的早期版本:当时security="none"的空链会完全跳过SecurityContextPersistenceFilter,访问该路径时无法从Session中读取已登录用户的认证信息,如果开发者需要在登录页判断用户是否已经登录、实现已登录用户自动跳转首页的逻辑,就会在普通安全链里再加一条同路径的permitAll规则,利用当时版本多安全链匹配的逻辑漏洞,让FORWARD类型的视图请求走普通安全链拿到认证信息,REQUEST请求走空链减少过滤器执行的性能开销。
  • 从Spring Security 4.2版本开始,这个逻辑问题就被修复了,permitAll本身就可以实现路径的匿名放行,和security="none"的访问控制效果完全一致,仅存在可以忽略的性能差异(多走十几层过滤器,单次请求耗时差不到1ms),同时配置两条规则完全多余,反而会在版本升级时引入匹配顺序、分发类型适配之类的兼容问题。

内容的提问来源于stack exchange,提问作者Jacob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:09:24