从 Spring 5 迁移到 Spring 6:“springSecurityFilterChain”问题

问题描述 投票:0回答:1

我目前正在将 Spring JSF 应用程序从 Spring 5 迁移到最新的 Spring 6。我使用的是 Java 17 以及

spring-boot-starter-parent
版本 3.3.5 和 Spring Security 版本 6.3.4。

在之前的版本中,我们在

web.xml
中为
springSecurityFilterChain
进行了以下配置:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>*.jsf</url-pattern>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>

我们现在使用 Spring Boot 将此配置转换为基于 Java 的配置。这是我们的

WebConfig
类中相应的 Bean 定义:

@Bean 
public FilterRegistrationBean<DelegatingFilterProxy> springSecurityFilterChain() { 
    FilterRegistrationBean<DelegatingFilterProxy> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new DelegatingFilterProxy("springSecurityFilterChain"));
    registrationBean.addUrlPatterns("*.jsf", "*.jsp"); 
    return registrationBean;
} 

但是,我在应用程序启动过程中遇到以下错误:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'springSecurityFilterChain': Unsatisfied dependency expressed through constructor parameter 0: Could not convert argument value of type [java.util.ArrayList] to required type [java.util.List]: Failed to convert value of type 'java.util.ArrayList' to required type 'java.util.List'; Cannot convert value of type 'org.springframework.boot.web.servlet.FilterRegistrationBean' to required type 'jakarta.servlet.Filter': no matching editors or conversion strategy found
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:757) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:237) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1375) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1212) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:313) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.14.jar:6.1.14]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.14.jar:6.1.14]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.14.jar:6.1.14]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.5.jar:3.3.5]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-3.3.5.jar:3.3.5]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) [spring-boot-3.3.5.jar:3.3.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) [spring-boot-3.3.5.jar:3.3.5]

Spring 似乎正在尝试将

FilterRegistrationBean
转换为
jakarta.servlet.Filter
,这导致了问题。

问题:

如何在 Spring 6 中正确定义

springSecurityFilterChain
Bean 以避免这种转换错误?

附加信息:

  • Java版本:17
  • Spring Boot版本:3.3.5
  • Spring安全版本:6.3.4

任何帮助或指导将不胜感激!

java spring-boot spring-security
1个回答
0
投票

您应该保留

web.xml
配置不变,并且不要尝试在 Spring 应用程序上下文中创建
springSecurityFilterChain
DelegatingFilterProxy 必须位于 servlet 容器的过滤器链中才能将 HTTP 请求转发到 Spring。

Spring 提供了一个名为 DelegatingFilterProxy 的 Filter 实现,它允许在 Servlet 容器的生命周期和 Spring 的 ApplicationContext 之间进行桥接。 Servlet容器允许使用自己的标准注册Filter实例,但它不知道Spring定义的Bean。您可以通过标准 Servlet 容器机制注册 DelegatingFilterProxy,但将所有工作委托给实现 Filter 的 Spring Bean。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.