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

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

我正在处理一个只使用基于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

  1. <filter>
  2. <filter-name>springSecurityFilterChain</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>springSecurityFilterChain</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

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

qv7cva1a

qv7cva1a1#

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

  1. /**
  2. * This class is a workaround to allow declaring SecurityFilterChain using xml
  3. * configuration and Java configuration. It listens to the Spring Application
  4. * context events ContextRefreshedEvent and add SecurityFilterChain beans,
  5. * declared in the Java configuration, to the FilterChainProxy.
  6. */
  7. @Configuration
  8. public static class MissingSecurityFilterChainsInitializer {
  9. private FilterChainProxy filterChainProxy;
  10. private List<SecurityFilterChain> filterChains;
  11. /**
  12. * @param filterChainProxy
  13. * @param myFilter
  14. */
  15. public MissingSecurityFilterChainsInitializer(FilterChainProxy filterChainProxy,
  16. List<SecurityFilterChain> myFilterChains) {
  17. super();
  18. this.filterChainProxy = filterChainProxy;
  19. this.filterChains = myFilterChains;
  20. }
  21. /**
  22. * Method listening to the Spring Application context initialization, detects
  23. * missing SecurityFilterChain from the FilterChainProxy and add the missing
  24. * chains to the FilterChainProxy.
  25. *
  26. * @param ctxRefreshed
  27. */
  28. @EventListener
  29. public void handleContextRefreshEvent(ContextRefreshedEvent ctxRefreshed) {
  30. List<SecurityFilterChain> missingChains = filterChains.stream()
  31. .filter(chain -> !filterChainProxy.getFilterChains().contains(chain)).collect(Collectors.toList());
  32. if (missingChains.isEmpty()) {
  33. return;
  34. }
  35. try {
  36. Field filterChainsField = filterChainProxy.getClass().getDeclaredField("filterChains");
  37. boolean accessibleStatus = filterChainsField.isAccessible();
  38. try {
  39. filterChainsField.setAccessible(true);
  40. List<SecurityFilterChain> chains = (List<SecurityFilterChain>) filterChainsField
  41. .get(filterChainProxy);
  42. if (chains == null) {
  43. throw new IllegalStateException(
  44. "Unable to add the missing security filter chains to the existing filter chains list of the FilterChainProxy. The list from the FilterChainProxy is null");
  45. }
  46. missingChains.forEach(chain -> chains.add(chain));
  47. } finally {
  48. filterChainsField.setAccessible(accessibleStatus);
  49. }
  50. } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
  51. throw new IllegalStateException(
  52. "Unable to add the missing security filter chains to the existing filter chains list of the FilterChainProxy: "
  53. + e.getMessage(),
  54. e);
  55. }
  56. }
  57. }
展开查看全部
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

相关问题