如何通过 XML 配置仅针对特定 URL 模式在 Spring Security 4 中禁用 CSRF?
Posted
技术标签:
【中文标题】如何通过 XML 配置仅针对特定 URL 模式在 Spring Security 4 中禁用 CSRF?【英文标题】:How to disable CSRF in Spring Security 4 only for specific URL pattern through XML configuration? 【发布时间】:2015-11-04 19:15:39 【问题描述】:如何在 Spring Security 4 中通过 XML 配置仅针对特定 URL 模式禁用 CSRF?
Spring-security.xml
<security:http auto-config="true" use-expressions="true" pattern="/ext/**">
<csrf disabled="true" />
</security:http>
<security:http auto-config="true" use-expressions="true" authentication-manager-ref="authenticationManager">
<security:intercept-url pattern="/auth/**" access="hasAnyRole('ROLE_USER')" />
<security:form-login login-page="/login" authentication-success-handler-ref="loginSuccessHandler" authentication-failure-url="/login" login-processing-url="/j_spring_security_check" />
<security:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
</security:http>
如果我只使用一个 security:http 块,我的代码可以正常工作,但是在我添加另一个块后,它会抛出如下错误:
错误
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter gov.in.controller.filter.LoginAdtAuthFailHdlr.usernamePasswordAuthenticationFilter; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter] is defined: expected single matching bean but found 2: org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0,org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#1
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 58 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter] is defined: expected single matching bean but found 2: org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0,org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#1
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 60 more
【问题讨论】:
【参考方案1】:仅通过 XML 更改无法实现。下面对我有用
Spring-security.xml
中的更改<security:http use-expressions="true" authentication-manager-ref="authenticationManager">
<security:intercept-url pattern="/auth/**" access="hasAnyRole('ROLE_USER')" />
<security:form-login login-page="/login" authentication-success-handler-ref="loginSuccessHandler" authentication-failure-url="/login" login-processing-url="/j_spring_security_check" />
<security:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<security:csrf request-matcher-ref="csrfSecurityRequestMatcher" />
</security:http>
CsrfSecurityRequestMatcher
public class CsrfSecurityRequestMatcher implements RequestMatcher
private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("/ext/**", null);
@Override
public boolean matches(HttpServletRequest request)
if(allowedMethods.matcher(request.getMethod()).matches())
return false;
return !unprotectedMatcher.matches(request);
【讨论】:
像魅力一样工作。感谢分享。我必须把@Component 放在类定义之前,这样spring 才能对匹配器进行组件扫描。 嘿,对不起,我是 java 新手,你能告诉我我需要创建CsrfSecurityRequestMatcher
类的位置吗
您需要在安全 xml 中创建一个 id 为 csrfSecurityRequestMatcher 的 bean,并对您的文件路径进行分类【参考方案2】:
您可以有两个(或更多)过滤器链:
<http pattern="/your-specific/**">
<!-- ... -->
<csrf disabled="true"/>
</http>
<http>
<!-- ... -->
</http>
【讨论】:
感谢您的回复。我在上面添加了一些 xml 和错误。当我添加第二个 http 块时,它会引发重复的 bean 错误。有什么建议吗? @ad-inf 您在LoginAdtAuthFailHdlr
中有对 UsernamePasswordAuthenticationFilter 的引用。使用两个form-login
,您将获得两个UsernamePasswordAuthenticationFilter
,您需要更改您的课程或删除一个表单登录。
也试过了。删除了所有元素,但错误仍然相同。更新了 xml
@ad-inf auto-config="true"
是form-login
等的简写(参见参考文档),我建议不要使用它。
'以上是关于如何通过 XML 配置仅针对特定 URL 模式在 Spring Security 4 中禁用 CSRF?的主要内容,如果未能解决你的问题,请参考以下文章
如何仅针对特定 url 添加 Spring Security 验证码过滤器