|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
- * Copyright 2002-2012 the original author or authors.
|
|
|
|
|
|
+ * Copyright 2002-2020 the original author or authors.
|
|
*
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* you may not use this file except in compliance with the License.
|
|
@@ -15,12 +15,19 @@
|
|
*/
|
|
*/
|
|
package org.springframework.security.config.http;
|
|
package org.springframework.security.config.http;
|
|
|
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
+import java.util.HashSet;
|
|
|
|
+import java.util.List;
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
|
+
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.Element;
|
|
|
|
|
|
import org.springframework.beans.BeanMetadataElement;
|
|
import org.springframework.beans.BeanMetadataElement;
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
|
|
+import org.springframework.beans.factory.config.RuntimeBeanReference;
|
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|
|
|
+import org.springframework.beans.factory.support.ManagedList;
|
|
import org.springframework.beans.factory.support.ManagedMap;
|
|
import org.springframework.beans.factory.support.ManagedMap;
|
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|
@@ -38,6 +45,10 @@ import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
|
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
|
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
|
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
|
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
|
import org.springframework.security.web.session.InvalidSessionStrategy;
|
|
import org.springframework.security.web.session.InvalidSessionStrategy;
|
|
|
|
+import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
|
|
|
+import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
|
|
|
+import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
|
|
|
+import org.springframework.security.web.util.matcher.RequestMatcher;
|
|
import org.springframework.util.ClassUtils;
|
|
import org.springframework.util.ClassUtils;
|
|
import org.springframework.util.StringUtils;
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
@@ -58,6 +69,8 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|
private String csrfRepositoryRef;
|
|
private String csrfRepositoryRef;
|
|
private BeanDefinition csrfFilter;
|
|
private BeanDefinition csrfFilter;
|
|
|
|
|
|
|
|
+ private String requestMatcherRef;
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
|
boolean disabled = element != null
|
|
boolean disabled = element != null
|
|
@@ -77,10 +90,9 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- String matcherRef = null;
|
|
|
|
if (element != null) {
|
|
if (element != null) {
|
|
this.csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY);
|
|
this.csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY);
|
|
- matcherRef = element.getAttribute(ATT_MATCHER);
|
|
|
|
|
|
+ this.requestMatcherRef = element.getAttribute(ATT_MATCHER);
|
|
}
|
|
}
|
|
|
|
|
|
if (!StringUtils.hasText(this.csrfRepositoryRef)) {
|
|
if (!StringUtils.hasText(this.csrfRepositoryRef)) {
|
|
@@ -100,8 +112,8 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|
.rootBeanDefinition(CsrfFilter.class);
|
|
.rootBeanDefinition(CsrfFilter.class);
|
|
builder.addConstructorArgReference(this.csrfRepositoryRef);
|
|
builder.addConstructorArgReference(this.csrfRepositoryRef);
|
|
|
|
|
|
- if (StringUtils.hasText(matcherRef)) {
|
|
|
|
- builder.addPropertyReference("requireCsrfProtectionMatcher", matcherRef);
|
|
|
|
|
|
+ if (StringUtils.hasText(this.requestMatcherRef)) {
|
|
|
|
+ builder.addPropertyReference("requireCsrfProtectionMatcher", this.requestMatcherRef);
|
|
}
|
|
}
|
|
|
|
|
|
this.csrfFilter = builder.getBeanDefinition();
|
|
this.csrfFilter = builder.getBeanDefinition();
|
|
@@ -172,4 +184,46 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|
csrfAuthenticationStrategy.addConstructorArgReference(this.csrfRepositoryRef);
|
|
csrfAuthenticationStrategy.addConstructorArgReference(this.csrfRepositoryRef);
|
|
return csrfAuthenticationStrategy.getBeanDefinition();
|
|
return csrfAuthenticationStrategy.getBeanDefinition();
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ void setIgnoreCsrfRequestMatchers(List<BeanDefinition> requestMatchers) {
|
|
|
|
+ if (!requestMatchers.isEmpty()) {
|
|
|
|
+ BeanMetadataElement requestMatcher;
|
|
|
|
+ if (StringUtils.hasText(this.requestMatcherRef)) {
|
|
|
|
+ requestMatcher = new RuntimeBeanReference(this.requestMatcherRef);
|
|
|
|
+ } else {
|
|
|
|
+ requestMatcher = new RootBeanDefinition(DefaultRequiresCsrfMatcher.class);
|
|
|
|
+ }
|
|
|
|
+ BeanDefinitionBuilder and = BeanDefinitionBuilder
|
|
|
|
+ .rootBeanDefinition(AndRequestMatcher.class);
|
|
|
|
+ BeanDefinitionBuilder negated = BeanDefinitionBuilder
|
|
|
|
+ .rootBeanDefinition(NegatedRequestMatcher.class);
|
|
|
|
+ BeanDefinitionBuilder or = BeanDefinitionBuilder
|
|
|
|
+ .rootBeanDefinition(OrRequestMatcher.class);
|
|
|
|
+ or.addConstructorArgValue(requestMatchers);
|
|
|
|
+ negated.addConstructorArgValue(or.getBeanDefinition());
|
|
|
|
+ List<BeanMetadataElement> ands = new ManagedList<>();
|
|
|
|
+ ands.add(requestMatcher);
|
|
|
|
+ ands.add(negated.getBeanDefinition());
|
|
|
|
+ and.addConstructorArgValue(ands);
|
|
|
|
+ this.csrfFilter.getPropertyValues()
|
|
|
|
+ .add("requireCsrfProtectionMatcher", and.getBeanDefinition());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static final class DefaultRequiresCsrfMatcher implements RequestMatcher {
|
|
|
|
+ private final HashSet<String> allowedMethods = new HashSet<>(
|
|
|
|
+ Arrays.asList("GET", "HEAD", "TRACE", "OPTIONS"));
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * (non-Javadoc)
|
|
|
|
+ *
|
|
|
|
+ * @see
|
|
|
|
+ * org.springframework.security.web.util.matcher.RequestMatcher#matches(javax.
|
|
|
|
+ * servlet.http.HttpServletRequest)
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public boolean matches(HttpServletRequest request) {
|
|
|
|
+ return !this.allowedMethods.contains(request.getMethod());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|