如何在 XML 配置中将 Spring-Security AntPathRequestMatcher 配置为不区分大小写
How to configure Spring-Security AntPathRequestMatcher to case insensitive in XML configuration
我们最近将 Spring-Security 从 3.X 升级到 5.6。大多数问题我们都可以解决,但有一件事证明是困难的。该问题是由默认行为的更改引起的 (3.1 vs. 5.6) of the AntPathRequestMatcher
(happened in Spring 4.2?)。
所以现在我们有了拦截器和过滤器,当使用不同的情况时它们不再被触发。
请注意:在旧版本中,与 spring 相关的所有内容都在 XML 中配置,现在必须保持这样。将来我们会将其更改为注释,但现在不会,因为由于应用程序的大小,这是一项艰巨的任务。
当前配置:
<bean class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
id="filterSecurityInterceptor">
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url
access="hasRole('ROLE_User')" pattern="/servlet/**"/>
<security:intercept-url
access="hasRole('ROLE_User')" pattern="/mobile.html" />
<security:intercept-url
access="hasAnyRole('ROLE_User', 'ROLE_OtherUser', 'ROLE_Guest')"
pattern="/offlineAssets/*" />
...
在 filter-security-metadata-source
的配置中,可以使用 request-matcher="ant"
配置不同的匹配器,但是我没有找到像以前那样使用不区分大小写的 AntMatcher 的方法。有一个 ticket 讨论引入一个 ciAnt
匹配器,但显然没有完成,因为它在当前的 spring-security 版本中不可用。
一种可能是在 intercept-url
级别上定义一个 request-matcher-ref
,但是我必须为每个规则定义一个匹配器 bean(并且有很多这样的规则)。这会使整个文件膨胀并且可读性会受到影响。不幸的是,将所有内容都转换为 ciRegex
也不是一种选择。必须有更简单的方法来做到这一点。
配置的过滤器链也有类似的情况,但是我们可以通过实现我们自己的 SecurityFilterChain
class 来解决问题,它会创建一个不区分大小写的匹配器,并且可以在XML 配置。然而,这对于 intercept-urls
是不可能的(我们未能构建 Map<RequestMatcher, Collection<ConfigAttribute>> requestMap
)
那么知道如何配置不区分大小写的 AntPathRequestMatcher 吗?
我想知道为什么你反对在你的 XML beans 配置中更冗长,因为这是自 1.x 版本以来 Spring 的工作方式,直到Java Config 已在生态系统中提升。我知道您正在管理一个大型应用程序,添加一些东西会使您的配置可维护性变得复杂。
一种方法(我认为你最好的选择)是添加 request-matcher-ref
和扩展 bean,它是 Spring antMatcher
的不敏感版本。
另一种方式可能是这些:
也许您可以在请求堆栈中实现自定义安全过滤器,并在其中检查自定义的不敏感 antMatcher 是否匹配。这些方式可以大大简化您的配置任务。
一些技巧,虽然不直接相关但对管理大型配置很有用 Spring Beans XML 文件:
1/ 您可以将 XML 配置拆分到模块专用文件中,以便更好地维护,并将它们导入主 XML 文件中,该文件绑定到您的 web 应用程序 Spring 上下文。
2/ 您可以一步步添加一些Java配置,简化您的日常维护工作。
3/ 您可以将属性文件中的所有 beans 字段初始化值外部化,并使用 @Profile
注释通过自定义 Spring 配置文件获取它们的值(dev、qa、prod 是开发期间的常用配置文件process) 和 @Value
注释来获取 POJO 中的值。
=> Beans 初始化将放在 XML 配置之外,随着您的进步,它会越来越轻。
正如我最初 post 中所建议的,我能想到的唯一方法是定义我们自己的 matcher-beans。现在这意味着添加大量 two-digit 的新 bean 定义会使我们的 XML 配置膨胀:
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher" id="antmatcherServlet">
<constructor-arg value="/servlet/**" index="0"/>
<constructor-arg index="1"><null/></constructor-arg>
<constructor-arg value="false" index="2"/>
</bean>
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher" id="antmatcherMobile">
<constructor-arg value="/mobile.html" index="0"/>
<constructor-arg index="1"><null/></constructor-arg>
<constructor-arg value="false" index="2"/>
</bean>
...
而参考是这样完成的:
<security:filter-security-metadata-source>
<security:intercept-url
access="hasRole('ROLE_User')" request-matcher-ref="antmatcherServlet"/>
<security:intercept-url
access="hasRole('ROLE_User')" request-matcher-ref="antmatcherMobile"/>
<security:intercept-url
access="hasAnyRole('ROLE_User', 'ROLE_OtherUser', 'ROLE_Guest')"
request-matcher-ref= "..." />
...
像这样的解决方案真的很棒而且不会破坏向后兼容性:
3.X:
<security:filter-security-metadata-source request-matcher="ant">
4.X、5.X
<security:filter-security-metadata-source request-matcher="ciAnt">
我们最近将 Spring-Security 从 3.X 升级到 5.6。大多数问题我们都可以解决,但有一件事证明是困难的。该问题是由默认行为的更改引起的 (3.1 vs. 5.6) of the AntPathRequestMatcher
(happened in Spring 4.2?)。
所以现在我们有了拦截器和过滤器,当使用不同的情况时它们不再被触发。
请注意:在旧版本中,与 spring 相关的所有内容都在 XML 中配置,现在必须保持这样。将来我们会将其更改为注释,但现在不会,因为由于应用程序的大小,这是一项艰巨的任务。
当前配置:
<bean class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
id="filterSecurityInterceptor">
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url
access="hasRole('ROLE_User')" pattern="/servlet/**"/>
<security:intercept-url
access="hasRole('ROLE_User')" pattern="/mobile.html" />
<security:intercept-url
access="hasAnyRole('ROLE_User', 'ROLE_OtherUser', 'ROLE_Guest')"
pattern="/offlineAssets/*" />
...
在 filter-security-metadata-source
的配置中,可以使用 request-matcher="ant"
配置不同的匹配器,但是我没有找到像以前那样使用不区分大小写的 AntMatcher 的方法。有一个 ticket 讨论引入一个 ciAnt
匹配器,但显然没有完成,因为它在当前的 spring-security 版本中不可用。
一种可能是在 intercept-url
级别上定义一个 request-matcher-ref
,但是我必须为每个规则定义一个匹配器 bean(并且有很多这样的规则)。这会使整个文件膨胀并且可读性会受到影响。不幸的是,将所有内容都转换为 ciRegex
也不是一种选择。必须有更简单的方法来做到这一点。
配置的过滤器链也有类似的情况,但是我们可以通过实现我们自己的 SecurityFilterChain
class 来解决问题,它会创建一个不区分大小写的匹配器,并且可以在XML 配置。然而,这对于 intercept-urls
是不可能的(我们未能构建 Map<RequestMatcher, Collection<ConfigAttribute>> requestMap
)
那么知道如何配置不区分大小写的 AntPathRequestMatcher 吗?
我想知道为什么你反对在你的 XML beans 配置中更冗长,因为这是自 1.x 版本以来 Spring 的工作方式,直到Java Config 已在生态系统中提升。我知道您正在管理一个大型应用程序,添加一些东西会使您的配置可维护性变得复杂。
一种方法(我认为你最好的选择)是添加 request-matcher-ref
和扩展 bean,它是 Spring antMatcher
的不敏感版本。
另一种方式可能是这些: 也许您可以在请求堆栈中实现自定义安全过滤器,并在其中检查自定义的不敏感 antMatcher 是否匹配。这些方式可以大大简化您的配置任务。
一些技巧,虽然不直接相关但对管理大型配置很有用 Spring Beans XML 文件:
1/ 您可以将 XML 配置拆分到模块专用文件中,以便更好地维护,并将它们导入主 XML 文件中,该文件绑定到您的 web 应用程序 Spring 上下文。
2/ 您可以一步步添加一些Java配置,简化您的日常维护工作。
3/ 您可以将属性文件中的所有 beans 字段初始化值外部化,并使用 @Profile
注释通过自定义 Spring 配置文件获取它们的值(dev、qa、prod 是开发期间的常用配置文件process) 和 @Value
注释来获取 POJO 中的值。
=> Beans 初始化将放在 XML 配置之外,随着您的进步,它会越来越轻。
正如我最初 post 中所建议的,我能想到的唯一方法是定义我们自己的 matcher-beans。现在这意味着添加大量 two-digit 的新 bean 定义会使我们的 XML 配置膨胀:
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher" id="antmatcherServlet">
<constructor-arg value="/servlet/**" index="0"/>
<constructor-arg index="1"><null/></constructor-arg>
<constructor-arg value="false" index="2"/>
</bean>
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher" id="antmatcherMobile">
<constructor-arg value="/mobile.html" index="0"/>
<constructor-arg index="1"><null/></constructor-arg>
<constructor-arg value="false" index="2"/>
</bean>
...
而参考是这样完成的:
<security:filter-security-metadata-source>
<security:intercept-url
access="hasRole('ROLE_User')" request-matcher-ref="antmatcherServlet"/>
<security:intercept-url
access="hasRole('ROLE_User')" request-matcher-ref="antmatcherMobile"/>
<security:intercept-url
access="hasAnyRole('ROLE_User', 'ROLE_OtherUser', 'ROLE_Guest')"
request-matcher-ref= "..." />
...
像这样的解决方案真的很棒而且不会破坏向后兼容性:
3.X:
<security:filter-security-metadata-source request-matcher="ant">
4.X、5.X
<security:filter-security-metadata-source request-matcher="ciAnt">