提问人:Plantexchen 提问时间:8/30/2023 最后编辑:Plantexchen 更新时间:10/20/2023 访问量:2903
更新到 Spring Security 5.8.6 后 JBoss 上的 Spring 请求匹配器问题
Spring request matcher issue on JBoss after update to Spring Security 5.8.6
问:
从 Spring Security 5.8.2 升级到 5.8.6 后,我在 JBoss EAP 7.4 上的部署遇到了问题(它在嵌入式 Tomcat 上工作正常)。我收到以下错误消息:
此方法无法确定这些模式是否为 Spring MVC 模式与否。如果此端点是 Spring MVC 端点,请使用 requestMatchers(MvcRequestMatcher);否则,请使用 requestMatchers(AntPathRequestMatcher)。
这是因为 servlet 上下文:{org.apache.jasper.servlet.JspServlet=[*.jsp, .jspx], javax.faces.webapp.FacesServlet=[/faces/, *.jsf, *.faces, *.xhtml], org.springframework.web.servlet.DispatcherServlet=[/]}。
对于每个 MvcRequestMatcher,将 MvcRequestMatcher#setServletPath 调用到 指示 servlet 路径。
我该如何解决这个问题?我们只有由 @Controller 注释的控制器,没有自定义 servlet。我的安全配置基本上如下:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class MySecurityConfig
{
@Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector)
{
return new MvcRequestMatcher.Builder(introspector);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity, MvcRequestMatcher.Builder mvc) throws Exception
{
return httpSecurity
.authorizeHttpRequests(auth ->
auth.requestMatchers(HttpMethod.OPTIONS)
.permitAll()
.requestMatchers(
mvc.pattern("/my-public-controller-1/**"),
mvc.pattern("/my-public-controller-2/**"),
mvc.pattern("/my-public-controller-3/**"))
.permitAll()
.anyRequest()
.authenticated())
.build();
}
}
我们使用 JBoss 默认配置。有一个和一个.最后一个文件如下所示:jboss-web.xml
jboss-deployment-structure.xml
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="com.sun.xml.bind"/>
</dependencies>
<exclude-subsystems>
<subsystem name="jaxrs"/>
<subsystem name="logging"/>
</exclude-subsystems>
</deployment>
</jboss-deployment-structure>
我试图像这样玩弄请求匹配器,但它没有帮助。
public SecurityFilterChain filterChain(HttpSecurity httpSecurity, MvcRequestMatcher.Builder mvc) throws Exception
{
return httpSecurity
.authorizeHttpRequests(auth ->
auth.requestMatchers(HttpMethod.OPTIONS)
.permitAll()
.requestMatchers(
mvc.pattern("/my-public-controller-1/**"),
mvc.pattern("/my-public-controller-2/**"),
mvc.pattern("/my-public-controller-3/**"),
antMatcher("/faces/*"))
.permitAll()
.anyRequest()
.authenticated())
.build();
}
我试图将 Faces 排除在外,但这一步毁了一切:jboss-deployment-structure.xml
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="com.sun.xml.bind"/>
</dependencies>
<exclude-subsystems>
<subsystem name="jaxrs"/>
<subsystem name="logging"/>
</exclude-subsystems>
<exclusions>
<module name="javax.faces.api" slot="main"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
我在这里看到了一个类似的问题,但我无法从中找到可行的解决方案:https://github.com/spring-projects/spring-security/issues/13568
顺便说一句,我们使用默认的servlet路径,所以错误消息中的这个建议对我来说毫无意义:
对于每个 MvcRequestMatcher,将 MvcRequestMatcher#setServletPath 调用到 指示 servlet 路径使
尽管如此,我还是尝试了类似的东西,但这也没有帮助:
@Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector)
{
return new MvcRequestMatcher.Builder(introspector).servletPath("");
}
答:
我的 SecurityConfig 如下所示:
package com.mycompany.ws.config
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.builders.WebSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
import org.springframework.web.servlet.handler.HandlerMappingIntrospector
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
fun webSecurityCustomizer(
introspector: HandlerMappingIntrospector,
): WebSecurityCustomizer {
val mvcMatcherBuilder = MvcRequestMatcher.Builder(introspector)
return WebSecurityCustomizer { web: WebSecurity ->
web.ignoring() // Spring Security should completely ignore URLs starting with /resources/ and so forth
.requestMatchers(
mvcMatcherBuilder.pattern("/resources/**"),
mvcMatcherBuilder.pattern("/static/**"),
mvcMatcherBuilder.pattern("/css/**"),
mvcMatcherBuilder.pattern("/js/**"),
mvcMatcherBuilder.pattern("/img/**"),
mvcMatcherBuilder.pattern("/lib/**"),
mvcMatcherBuilder.pattern("/favicon.ico")
)
}
}
@Bean
@Throws(Exception::class)
fun securityFilterChain(
http: HttpSecurity,
): SecurityFilterChain {
return http
.authorizeHttpRequests { cfg ->
cfg.anyRequest().permitAll()
}
.csrf { it.disable() }
.cors { it.disable() }
.formLogin { it.disable() }
.build()
}
companion object {
val log: Logger = LogManager.getLogger(this::class.java)
}
}
所以你在 Wildfy 上。在 web-inf 下添加 jboss-deployment-structure.xml 文件,你应该可以开始了。
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclude-subsystems>
<subsystem name="logging" />
<subsystem name="jsf" />
</exclude-subsystems>
</deployment>
</jboss-deployment-structure>
我在 Wildfly 27.0.1 上使用 Spring Boot 3.1 和 JDK 17。
根据错误消息 - 类路径上有 3 个 servlet。Dispatcher 由 Spring Boot 提供,另外 2 个由 Wildfly 为 JSF 和 JSP 提供。
通过添加此文件,我们告诉应用程序服务器 - 不要在我的应用程序类路径上添加 JSF servlet。
可以在独立的 .xml 文件中检查子系统名称。
因为我在独立的 .xml 中注释了 jsp-configorg.apache.jasper.servlet.JspServlet=[*.jsp, .jspx]
评论