【发布时间】:2018-06-28 14:58:18
【问题描述】:
我正在将 Spring 3 webapp 迁移到 Spring 4 Spring Boot webapp。
在 Spring 3 中,我使用了 Spring Security 的基于 XML 的配置,并定义了如下内容:
<sec:http pattern="/**/*.css" security="none" />
<sec:http pattern="/**/*.js" security="none" />
<sec:http pattern="^.*\?basic-auth=on$" request-matcher="regex" create-session="never">
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<sec:http-basic />
</sec:http>
<sec:http name="formAuth" pattern="^(.*(\?|&)form-auth=on)|/servlet/login\.html|/servlet/!login\.html$" request-matcher="regex"
entry-point-ref="security.formLogin.entryPoint">
<sec:intercept-url pattern="/servlet/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/servlet/!login.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<sec:form-login login-page="/servlet/login.html"
login-processing-url="/servlet/!login.html"
default-target-url="/" authentication-failure-handler-ref="accessDeniedHandler"></sec:form-login>
</sec:http>
一些解释: 整个页面(不包括 CSS、JS)都受访问保护。 有多种登录机制,如 Kerberos(未显示)、基本身份验证和表单登录。如果首选登录机制 Kerberos 失败,用户将被重定向到表单登录。当请求带有 '&form-auth=on' 附录的相同 url 时会发生这种情况,因此名为 'formAuth' 的过滤器链被激活。
问题: 如果我尝试访问 JS 或 CSS 文件(不受保护的资源),我得到了异常 AuthenticationCredentialsNotFoundException
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:379)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:223)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:115)
我的假设 Spring Boot 自动将每个 GenericFilterBean 添加到过滤器链 (see here)。 所以我的每一个 GenericFilterBean 类型的 bean 都被添加到 ApplicationFilterChain 和 SpringSecurityFilterChain 中。要拒绝 Spring Boot 将此过滤器添加到 ApplicationFilterChain,我必须创建一个 FilterRegistrationBean 类型的 bean 并将其设置为禁用。
但是我怎样才能为 XML 元素 sec:intercept-url, sec:http-basic, sec:form-login 创建这样的 bean,它隐式地创建像 UsernamePasswordAuthenticationFilter 或 BasicAuthenticationFilter 这样的 GenericFilterBeans。 XML 元素没有可用于创建 FilterRegistrationBean 的 name 或 id 属性。
【问题讨论】:
-
这是 Spring Security 中的一个错误/缺失功能,请参阅 github.com/spring-projects/spring-boot/issues/1594 和 github.com/spring-projects/spring-security/issues/2948。您应该使用 Java 配置。
-
好的。之所以有效,是因为我没有在 Spring Boot 捕获的应用程序上下文中创建 bean!?
-
对不起,我不明白你最后的评论。 Spring Boot 与 Java 配置一起工作,因为它得到了更好的支持。主要问题是,Spring Boot 自动注册所有 servlet 过滤器,恕我直言 Spring Security 存在设计错误,它使用 servlet 过滤器作为其安全过滤器。
标签: xml spring-boot spring-security