1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.security.intercept.web;
17
18 import org.springframework.security.ConfigAttributeDefinition;
19 import org.springframework.security.util.UrlMatcher;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 import java.util.Map;
25 import java.util.LinkedHashMap;
26 import java.util.Iterator;
27 import java.util.HashMap;
28 import java.util.Set;
29 import java.util.HashSet;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.Collections;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class DefaultFilterInvocationDefinitionSource implements FilterInvocationDefinitionSource {
57
58 private static final Set HTTP_METHODS = new HashSet(Arrays.asList(new String[]{ "DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "TRACE" }));
59
60 protected final Log logger = LogFactory.getLog(getClass());
61
62
63
64
65
66 private Map requestMap = new LinkedHashMap();
67
68 private Map httpMethodMap = new HashMap();
69
70 private UrlMatcher urlMatcher;
71
72 private boolean stripQueryStringFromUrls;
73
74
75
76
77
78 DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher) {
79 this.urlMatcher = urlMatcher;
80 }
81
82
83
84
85
86
87
88
89
90 public DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher, LinkedHashMap requestMap) {
91 this.urlMatcher = urlMatcher;
92
93 Iterator iterator = requestMap.entrySet().iterator();
94
95 while (iterator.hasNext()) {
96 Map.Entry entry = (Map.Entry) iterator.next();
97 RequestKey reqKey = (RequestKey) entry.getKey();
98 addSecureUrl(reqKey.getUrl(), reqKey.getMethod(), (ConfigAttributeDefinition) entry.getValue());
99 }
100 }
101
102
103
104 void addSecureUrl(String pattern, ConfigAttributeDefinition attr) {
105 addSecureUrl(pattern, null, attr);
106 }
107
108
109
110
111
112
113
114 void addSecureUrl(String pattern, String method, ConfigAttributeDefinition attr) {
115 Map mapToUse = getRequestMapForHttpMethod(method);
116
117 mapToUse.put(urlMatcher.compile(pattern), attr);
118
119 if (logger.isDebugEnabled()) {
120 logger.debug("Added URL pattern: " + pattern + "; attributes: " + attr +
121 (method == null ? "" : " for HTTP method '" + method + "'"));
122 }
123 }
124
125
126
127
128
129
130 private Map getRequestMapForHttpMethod(String method) {
131 if (method == null) {
132 return requestMap;
133 }
134 if (!HTTP_METHODS.contains(method)) {
135 throw new IllegalArgumentException("Unrecognised HTTP method: '" + method + "'");
136 }
137
138 Map methodRequestmap = (Map) httpMethodMap.get(method);
139
140 if (methodRequestmap == null) {
141 methodRequestmap = new LinkedHashMap();
142 httpMethodMap.put(method, methodRequestmap);
143 }
144
145 return methodRequestmap;
146 }
147
148 public Collection getConfigAttributeDefinitions() {
149 return Collections.unmodifiableCollection(getRequestMap().values());
150 }
151
152 public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException {
153 if ((object == null) || !this.supports(object.getClass())) {
154 throw new IllegalArgumentException("Object must be a FilterInvocation");
155 }
156
157 String url = ((FilterInvocation) object).getRequestUrl();
158 String method = ((FilterInvocation) object).getHttpRequest().getMethod();
159
160 return lookupAttributes(url, method);
161 }
162
163 protected ConfigAttributeDefinition lookupAttributes(String url) {
164 return lookupAttributes(url, null);
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 public ConfigAttributeDefinition lookupAttributes(String url, String method) {
183 if (stripQueryStringFromUrls) {
184
185 int firstQuestionMarkIndex = url.indexOf("?");
186
187 if (firstQuestionMarkIndex != -1) {
188 url = url.substring(0, firstQuestionMarkIndex);
189 }
190 }
191
192 if (urlMatcher.requiresLowerCaseUrl()) {
193 url = url.toLowerCase();
194
195 if (logger.isDebugEnabled()) {
196 logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'");
197 }
198 }
199
200 ConfigAttributeDefinition attributes = null;
201
202 Map methodSpecificMap = (Map) httpMethodMap.get(method);
203
204 if (methodSpecificMap != null) {
205 attributes = lookupUrlInMap(methodSpecificMap, url);
206 }
207
208 if (attributes == null) {
209 attributes = lookupUrlInMap(requestMap, url);
210 }
211
212 return attributes;
213 }
214
215 private ConfigAttributeDefinition lookupUrlInMap(Map requestMap, String url) {
216 Iterator entries = requestMap.entrySet().iterator();
217
218 while (entries.hasNext()) {
219 Map.Entry entry = (Map.Entry) entries.next();
220 Object p = entry.getKey();
221 boolean matched = urlMatcher.pathMatchesUrl(p, url);
222
223 if (logger.isDebugEnabled()) {
224 logger.debug("Candidate is: '" + url + "'; pattern is " + p + "; matched=" + matched);
225 }
226
227 if (matched) {
228 return (ConfigAttributeDefinition) entry.getValue();
229 }
230 }
231
232 return null;
233 }
234
235 public boolean supports(Class clazz) {
236 return FilterInvocation.class.isAssignableFrom(clazz);
237 }
238
239 public int getMapSize() {
240 return this.requestMap.size();
241 }
242
243 Map getRequestMap() {
244 return requestMap;
245 }
246
247 protected UrlMatcher getUrlMatcher() {
248 return urlMatcher;
249 }
250
251 public boolean isConvertUrlToLowercaseBeforeComparison() {
252 return urlMatcher.requiresLowerCaseUrl();
253 }
254
255 public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
256 this.stripQueryStringFromUrls = stripQueryStringFromUrls;
257 }
258 }