1
1
/*
2
- * Copyright 2002-2012 the original author or authors.
2
+ * Copyright 2002-2020 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
15
15
*/
16
16
package org .springframework .security .config .http ;
17
17
18
+ import java .util .Arrays ;
19
+ import java .util .HashSet ;
20
+ import java .util .List ;
21
+ import javax .servlet .http .HttpServletRequest ;
22
+
18
23
import org .w3c .dom .Element ;
19
24
20
25
import org .springframework .beans .BeanMetadataElement ;
21
26
import org .springframework .beans .factory .config .BeanDefinition ;
27
+ import org .springframework .beans .factory .config .RuntimeBeanReference ;
22
28
import org .springframework .beans .factory .parsing .BeanComponentDefinition ;
23
29
import org .springframework .beans .factory .support .BeanDefinitionBuilder ;
30
+ import org .springframework .beans .factory .support .ManagedList ;
24
31
import org .springframework .beans .factory .support .ManagedMap ;
25
32
import org .springframework .beans .factory .support .RootBeanDefinition ;
26
33
import org .springframework .beans .factory .xml .BeanDefinitionParser ;
38
45
import org .springframework .security .web .servlet .support .csrf .CsrfRequestDataValueProcessor ;
39
46
import org .springframework .security .web .session .InvalidSessionAccessDeniedHandler ;
40
47
import org .springframework .security .web .session .InvalidSessionStrategy ;
48
+ import org .springframework .security .web .util .matcher .AndRequestMatcher ;
49
+ import org .springframework .security .web .util .matcher .NegatedRequestMatcher ;
50
+ import org .springframework .security .web .util .matcher .OrRequestMatcher ;
51
+ import org .springframework .security .web .util .matcher .RequestMatcher ;
41
52
import org .springframework .util .ClassUtils ;
42
53
import org .springframework .util .StringUtils ;
43
54
@@ -58,6 +69,8 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
58
69
private String csrfRepositoryRef ;
59
70
private BeanDefinition csrfFilter ;
60
71
72
+ private String requestMatcherRef ;
73
+
61
74
@ Override
62
75
public BeanDefinition parse (Element element , ParserContext pc ) {
63
76
boolean disabled = element != null
@@ -77,10 +90,9 @@ public BeanDefinition parse(Element element, ParserContext pc) {
77
90
}
78
91
}
79
92
80
- String matcherRef = null ;
81
93
if (element != null ) {
82
94
this .csrfRepositoryRef = element .getAttribute (ATT_REPOSITORY );
83
- matcherRef = element .getAttribute (ATT_MATCHER );
95
+ this . requestMatcherRef = element .getAttribute (ATT_MATCHER );
84
96
}
85
97
86
98
if (!StringUtils .hasText (this .csrfRepositoryRef )) {
@@ -100,8 +112,8 @@ public BeanDefinition parse(Element element, ParserContext pc) {
100
112
.rootBeanDefinition (CsrfFilter .class );
101
113
builder .addConstructorArgReference (this .csrfRepositoryRef );
102
114
103
- if (StringUtils .hasText (matcherRef )) {
104
- builder .addPropertyReference ("requireCsrfProtectionMatcher" , matcherRef );
115
+ if (StringUtils .hasText (this . requestMatcherRef )) {
116
+ builder .addPropertyReference ("requireCsrfProtectionMatcher" , this . requestMatcherRef );
105
117
}
106
118
107
119
this .csrfFilter = builder .getBeanDefinition ();
@@ -172,4 +184,46 @@ BeanDefinition getCsrfLogoutHandler() {
172
184
csrfAuthenticationStrategy .addConstructorArgReference (this .csrfRepositoryRef );
173
185
return csrfAuthenticationStrategy .getBeanDefinition ();
174
186
}
187
+
188
+ void setIgnoreCsrfRequestMatchers (List <BeanDefinition > requestMatchers ) {
189
+ if (!requestMatchers .isEmpty ()) {
190
+ BeanMetadataElement requestMatcher ;
191
+ if (StringUtils .hasText (this .requestMatcherRef )) {
192
+ requestMatcher = new RuntimeBeanReference (this .requestMatcherRef );
193
+ } else {
194
+ requestMatcher = new RootBeanDefinition (DefaultRequiresCsrfMatcher .class );
195
+ }
196
+ BeanDefinitionBuilder and = BeanDefinitionBuilder
197
+ .rootBeanDefinition (AndRequestMatcher .class );
198
+ BeanDefinitionBuilder negated = BeanDefinitionBuilder
199
+ .rootBeanDefinition (NegatedRequestMatcher .class );
200
+ BeanDefinitionBuilder or = BeanDefinitionBuilder
201
+ .rootBeanDefinition (OrRequestMatcher .class );
202
+ or .addConstructorArgValue (requestMatchers );
203
+ negated .addConstructorArgValue (or .getBeanDefinition ());
204
+ List <BeanMetadataElement > ands = new ManagedList <>();
205
+ ands .add (requestMatcher );
206
+ ands .add (negated .getBeanDefinition ());
207
+ and .addConstructorArgValue (ands );
208
+ this .csrfFilter .getPropertyValues ()
209
+ .add ("requireCsrfProtectionMatcher" , and .getBeanDefinition ());
210
+ }
211
+ }
212
+
213
+ private static final class DefaultRequiresCsrfMatcher implements RequestMatcher {
214
+ private final HashSet <String > allowedMethods = new HashSet <>(
215
+ Arrays .asList ("GET" , "HEAD" , "TRACE" , "OPTIONS" ));
216
+
217
+ /*
218
+ * (non-Javadoc)
219
+ *
220
+ * @see
221
+ * org.springframework.security.web.util.matcher.RequestMatcher#matches(javax.
222
+ * servlet.http.HttpServletRequest)
223
+ */
224
+ @ Override
225
+ public boolean matches (HttpServletRequest request ) {
226
+ return !this .allowedMethods .contains (request .getMethod ());
227
+ }
228
+ }
175
229
}
0 commit comments