1+ /**
2+ * OWASP Enterprise Security API (ESAPI)
3+ *
4+ * This file is part of the Open Web Application Security Project (OWASP)
5+ * Enterprise Security API (ESAPI) project. For details, please see
6+ * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
7+ *
8+ * Copyright (c) 2007 - The OWASP Foundation
9+ *
10+ * The ESAPI is published by OWASP under the BSD license. You should read and accept the
11+ * LICENSE before you use, modify, and/or redistribute this software.
12+ *
13+ * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
14+ * @created 2007
15+ */
16+ package org .owasp .esapi .filters ;
17+
18+ import java .io .IOException ;
19+ import java .util .Date ;
20+ import java .util .Stack ;
21+
22+ import javax .servlet .Filter ;
23+ import javax .servlet .FilterChain ;
24+ import javax .servlet .FilterConfig ;
25+ import javax .servlet .ServletException ;
26+ import javax .servlet .ServletRequest ;
27+ import javax .servlet .ServletResponse ;
28+ import javax .servlet .http .HttpServletRequest ;
29+ import javax .servlet .http .HttpSession ;
30+
31+ /**
32+ * Servlet filter class.
33+ */
34+ public class RequestRateThrottleFilter implements Filter
35+ {
36+
37+ private int hits = 5 ;
38+
39+ private int period = 10 ;
40+
41+ private static final String HITS = "hits" ;
42+
43+ private static final String PERIOD = "period" ;
44+
45+ /**
46+ * Called by the web container to indicate to a filter that it is being
47+ * placed into service. The servlet container calls the init method exactly
48+ * once after instantiating the filter. The init method must complete
49+ * successfully before the filter is asked to do any filtering work.
50+ *
51+ * @param filterConfig
52+ * configuration object
53+ */
54+ public void init (FilterConfig filterConfig )
55+ {
56+ hits = Integer .parseInt (filterConfig .getInitParameter (HITS ));
57+ period = Integer .parseInt (filterConfig .getInitParameter (PERIOD ));
58+ }
59+
60+ /**
61+ * Checks to see if the current session has exceeded the allowed number
62+ * of requests in the specified time period. If the threshold has been
63+ * exceeded, then a short error message is written to the output stream and
64+ * no further processing is done on the request. Otherwise the request is
65+ * processed as normal.
66+ */
67+ public void doFilter (ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException
68+ {
69+ HttpServletRequest httpRequest = (HttpServletRequest ) request ;
70+ HttpSession session = httpRequest .getSession (true );
71+
72+ synchronized ( session ) {
73+ Stack times = (Stack ) session .getAttribute ("times" );
74+ if (times == null )
75+ {
76+ times = new Stack ();
77+ times .push (new Date (0 ));
78+ session .setAttribute ("times" , times );
79+ }
80+ times .push (new Date ());
81+ if (times .size () >= hits )
82+ {
83+ times .removeElementAt (0 );
84+ }
85+ Date newest = (Date ) times .get (times .size () - 1 );
86+ Date oldest = (Date ) times .get (0 );
87+ long elapsed = newest .getTime () - oldest .getTime ();
88+ if (elapsed < period * 1000 ) // seconds
89+ {
90+ response .getWriter ().println ("Request rate too high" );
91+ return ;
92+ }
93+ }
94+ chain .doFilter (request , response );
95+ }
96+
97+ /**
98+ * Called by the web container to indicate to a filter that it is being
99+ * taken out of service. This method is only called once all threads within
100+ * the filter's doFilter method have exited or after a timeout period has
101+ * passed. After the web container calls this method, it will not call the
102+ * doFilter method again on this instance of the filter.
103+ */
104+ public void destroy ()
105+ {
106+ // finalize
107+ }
108+
109+ }
0 commit comments