Spring Security -如何混合xml< security:http>和Java SecurityFilterChain声明配置?

9ceoxa92  于 2022-10-30  发布在  Spring
关注(0)|答案(3)|浏览(229)

我正在处理一个只使用基于XMLSchema的Spring配置的应用程序,我正在慢慢地引入基于Java的配置。
不幸的是,我不能同时使用Spring Security html xml元素和基于Java的SecurityFilterChain配置。
当我检查FilterChainProxy中的filterChains列表时,它只包含来自xml配置的过滤器链。尽管调用了创建SecurityFilterChain bean的Java方法,但该过滤器链并没有添加到FilterChainProxy中。
如果我从xml配置中删除html元素,Java配置中的SecurityFilterChain将被添加到FilterChainProxy中,并按预期进行调用。
我正在使用的Spring版本:

  • Spring框架:5.3.16
  • Spring安全性:5.6.2

下面是我尝试同时使用的xml配置和Java配置:
第一个
web.xml

<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>/*</url-pattern>
</filter-mapping>

我是否犯了错误,是否有办法实现我的愿望,或者根本不可能?

qv7cva1a

qv7cva1a1#

在找到更好的解决方案之前,可以使用下面的解决方案(如果确实需要)。一旦Spring应用程序上下文初始化,它就将缺少的SecurityFilterChain添加到FilterChainProxy。我在Spring Security5.6.2上实现了它。由于它使用反射,因此在Spring Security版本的任何升级之后,它都可能会中断。

/**
     * This class is a workaround to allow declaring SecurityFilterChain using xml
     * configuration and Java configuration. It listens to the Spring Application
     * context events ContextRefreshedEvent and add SecurityFilterChain beans,
     * declared in the Java configuration, to the FilterChainProxy.
     */
    @Configuration
    public static class MissingSecurityFilterChainsInitializer {

        private FilterChainProxy filterChainProxy;

        private List<SecurityFilterChain> filterChains;

        /**
         * @param filterChainProxy
         * @param myFilter
         */
        public MissingSecurityFilterChainsInitializer(FilterChainProxy filterChainProxy,
                List<SecurityFilterChain> myFilterChains) {
            super();
            this.filterChainProxy = filterChainProxy;
            this.filterChains = myFilterChains;
        }

        /**
         * Method listening to the Spring Application context initialization, detects
         * missing SecurityFilterChain from the FilterChainProxy and add the missing
         * chains to the FilterChainProxy.
         * 
         * @param ctxRefreshed
         */
        @EventListener
        public void handleContextRefreshEvent(ContextRefreshedEvent ctxRefreshed) {
            List<SecurityFilterChain> missingChains = filterChains.stream()
                    .filter(chain -> !filterChainProxy.getFilterChains().contains(chain)).collect(Collectors.toList());

            if (missingChains.isEmpty()) {
                return;
            }

            try {
                Field filterChainsField = filterChainProxy.getClass().getDeclaredField("filterChains");
                boolean accessibleStatus = filterChainsField.isAccessible();
                try {
                    filterChainsField.setAccessible(true);
                    List<SecurityFilterChain> chains = (List<SecurityFilterChain>) filterChainsField
                            .get(filterChainProxy);
                    if (chains == null) {
                        throw new IllegalStateException(
                                "Unable to add the missing security filter chains to the existing filter chains list of the FilterChainProxy. The list from the FilterChainProxy is null");
                    }
                    missingChains.forEach(chain -> chains.add(chain));
                } finally {
                    filterChainsField.setAccessible(accessibleStatus);
                }
            } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
                throw new IllegalStateException(
                        "Unable to add the missing security filter chains to the existing filter chains list of the FilterChainProxy: "
                                + e.getMessage(),
                        e);

            }
        }
    }
sigwle7e

sigwle7e2#

根据我的经验,将Java bean配置与XML配置混合使用是行不通的。我们必须使用基于XML或基于Java的配置。我尝试以这种方式配置内容安全策略https://www.baeldung.com/spring-security-csp,同时我已经实现了XML bean配置。无论如何,它都无法找到httpSecurity bean进行初始化。因此,我按照这种方式https://www.stackhawk.com/blog/spring-content-security-policy-guide-what-it-is-and-how-to-enable-it/#xml并将其添加到我的applicationContext.xml

c9qzyr3d

c9qzyr3d3#

过滤器是由Servlet容器(如Tomcat或Jetty)创建、维护和销毁的。您在web.xml中声明过滤器,Web容器通过调用它们的init(FilterConfig config)方法来初始化它们。然后,此过滤器将实际的预处理和后处理任务委托给Spring Security框架提供的Spring感知过滤器实现。
每次请求或响应到达并与过滤器的URL模式匹配时,Servlet容器都会调用DelegatingFilterProxy的doFilter()方法来过滤请求和响应。
此方法可以访问ServletRequest、ServletResponse和FilterChain对象,这意味着它可以在将请求发送到Servlet或将响应发送到客户端之前修改请求标头、响应标头和响应正文。FilterChain对象用于将请求路由到链中的另一个筛选器,以便进一步处理。
阅读更多信息:https://javarevisited.blogspot.com/2017/05/how-to-enable-spring-security-in-java-web-application.html#ixzz7QWQrVPCb

相关问题