-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
SecurityFilter.java
132 lines (117 loc) · 5.6 KB
/
SecurityFilter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* #%L
* BroadleafCommerce Common Libraries
* %%
* Copyright (C) 2009 - 2013 Broadleaf Commerce
* %%
* Licensed under the Broadleaf Fair Use License Agreement, Version 1.0
* (the "Fair Use License" located at http://license.broadleafcommerce.org/fair_use_license-1.0.txt)
* unless the restrictions on use therein are violated and require payment to Broadleaf in which case
* the Broadleaf End User License Agreement (EULA), Version 1.1
* (the "Commercial License" located at http://license.broadleafcommerce.org/commercial_license-1.1.txt)
* shall apply.
*
* Alternatively, the Commercial License may be replaced with a mutually agreed upon license (the "Custom License")
* between you and Broadleaf Commerce. You may not use this file except in compliance with the applicable license.
* #L%
*/
package org.broadleafcommerce.common.security.handler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.common.security.service.ExploitProtectionService;
import org.broadleafcommerce.common.security.service.StaleStateProtectionService;
import org.broadleafcommerce.common.security.service.StaleStateServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.filter.GenericFilterBean;
import java.io.IOException;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Checks the validity of the CSRF token on every POST request. Also Checks the validity of the state token on every POST
* request. Its purpose is to help protect against a page being
* submitted with stale state. This can occur when key state has changed (either in session, or otherwise) that makes the
* current POST request no longer viable. See {@link StaleStateProtectionService} for more info on purpose and usage.
* </p>
* You can inject excluded Request URI patterns to bypass this filter.
* This filter uses the AntPathRequestMatcher which compares a pre-defined ant-style pattern against the URL
* ({@code servletPath + pathInfo}) of an {@code HttpServletRequest}.
* This allows you to use wildcard matching as well, for example {@code /**} or {@code **}
*
* @see AntPathRequestMatcher
*
* @author Jeff Fischer
*/
public class SecurityFilter extends GenericFilterBean {
protected static final Log LOG = LogFactory.getLog(SecurityFilter.class);
@Autowired
@Qualifier("blStaleStateProtectionService")
protected StaleStateProtectionService staleStateProtectionService;
@Autowired
@Qualifier("blExploitProtectionService")
protected ExploitProtectionService exploitProtectionService;
protected List<String> excludedRequestPatterns;
@Override
public void doFilter(ServletRequest baseRequest, ServletResponse baseResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) baseRequest;
HttpServletResponse response = (HttpServletResponse) baseResponse;
boolean excludedRequestFound = false;
if (excludedRequestPatterns != null && excludedRequestPatterns.size() > 0) {
for (String pattern : excludedRequestPatterns) {
RequestMatcher matcher = new AntPathRequestMatcher(pattern);
if (matcher.matches(request)) {
excludedRequestFound = true;
break;
}
}
}
// We only validate CSRF tokens on POST
if (request.getMethod().equals("POST") && !excludedRequestFound) {
String requestToken = request.getParameter(exploitProtectionService.getCsrfTokenParameter());
try {
exploitProtectionService.compareToken(requestToken);
} catch (ServiceException e) {
throw new ServletException(e);
}
}
if (staleStateProtectionService.isEnabled()) {
// We only validate tokens on POST
// Catch attempts to update form data from a stale page (i.e. a important state change has taken place for this session)
if (request.getMethod().equals("POST") && !excludedRequestFound) {
String requestToken = request.getParameter(staleStateProtectionService.getStateVersionTokenParameter());
try {
staleStateProtectionService.compareToken(requestToken);
} catch (StaleStateServiceException e) {
throw new ServletException(e);
}
}
}
chain.doFilter(request, response);
}
public List<String> getExcludedRequestPatterns() {
return excludedRequestPatterns;
}
/**
* This allows you to declaratively set a list of excluded Request Patterns
*
* <bean id="blCsrfFilter" class="org.broadleafcommerce.common.security.handler.CsrfFilter" >
* <property name="excludedRequestPatterns">
* <list>
* <value>/exclude-me/**</value>
* </list>
* </property>
* </bean>
*
**/
public void setExcludedRequestPatterns(List<String> excludedRequestPatterns) {
this.excludedRequestPatterns = excludedRequestPatterns;
}
}