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 package fr.paris.lutece.portal.web.upload;
35
36 import fr.paris.lutece.portal.service.util.AppLogService;
37
38 import java.io.IOException;
39
40 import java.util.HashMap;
41 import java.util.LinkedList;
42 import java.util.Map;
43
44 import javax.servlet.Filter;
45 import javax.servlet.FilterChain;
46 import javax.servlet.FilterConfig;
47 import javax.servlet.ServletException;
48 import javax.servlet.ServletRequest;
49 import javax.servlet.ServletResponse;
50
51
52
53
54
55
56
57 public class DosGuardFilter implements Filter
58 {
59
60 private static final int INITIAL_CAPACITY = 100;
61 private FilterConfig _filterConfig;
62
63
64 private int _nMinContentLength;
65
66
67 private int _nMinInterval;
68
69
70 private Map<String, Long> _mapLastRequestTimes;
71
72
73
74 private LinkedList<Entry> _listOrderedRequests;
75
76
77
78
79 @Override
80 public void init( FilterConfig config ) throws ServletException
81 {
82 _filterConfig = config;
83 _mapLastRequestTimes = new HashMap<String, Long>( INITIAL_CAPACITY );
84 _listOrderedRequests = new LinkedList<Entry>( );
85
86 try
87 {
88 String paramValue = _filterConfig.getInitParameter( "minContentLength" );
89
90 if ( paramValue != null )
91 {
92 _nMinContentLength = Integer.parseInt( paramValue );
93 }
94
95 paramValue = _filterConfig.getInitParameter( "minInterval" );
96
97 if ( paramValue != null )
98 {
99 _nMinInterval = Integer.parseInt( paramValue );
100 }
101 }
102 catch ( NumberFormatException ex )
103 {
104 ServletException servletEx = new ServletException( ex.getMessage( ) );
105 servletEx.initCause( ex );
106 throw servletEx;
107 }
108 }
109
110
111
112
113 @Override
114 public void destroy( )
115 {
116
117 }
118
119
120
121
122 @Override
123 public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
124 throws IOException, ServletException
125 {
126
127 if ( this.isAllowed( request.getRemoteAddr( ), request.getContentLength( ) ) )
128 {
129 chain.doFilter( request, response );
130 }
131 else
132 {
133 throw new ServletException( "DOS Guard : Too many upload from the same IP !" );
134 }
135 }
136
137
138
139
140
141
142
143
144 public synchronized boolean isAllowed( String strRemoteAddr, int iContentLength )
145 {
146 AppLogService.debug( "DosGuard : isAllowed(" + strRemoteAddr + ", " + iContentLength + ")" );
147
148
149 if ( iContentLength < _nMinContentLength )
150 {
151 AppLogService.debug( "ContentLength is below minimum, ignored" );
152
153 return true;
154 }
155
156
157 long lRequestTime = System.currentTimeMillis( );
158 AppLogService.debug( "Request time : " + lRequestTime );
159
160
161 Long previousRequestTime = _mapLastRequestTimes.get( strRemoteAddr );
162 AppLogService.debug( "Previous request time : " + previousRequestTime );
163
164 if ( previousRequestTime != null )
165 {
166 AppLogService.debug( "IP is in the map" );
167
168
169 if ( lRequestTime > ( previousRequestTime.longValue( ) + _nMinInterval ) )
170 {
171 AppLogService.debug( "IP is allowed to make a new request" );
172
173
174 this.cleanExpiredEntries( );
175
176
177 _mapLastRequestTimes.put( strRemoteAddr, Long.valueOf( lRequestTime ) );
178
179
180 _listOrderedRequests.addFirst( new Entry( strRemoteAddr, lRequestTime ) );
181
182 return true;
183 }
184
185 AppLogService.debug( "IP is not allowed to make a new request" );
186
187 return false;
188 }
189
190 AppLogService.debug( "IP is not in the map" );
191
192
193 this.cleanExpiredEntries( );
194
195
196 _mapLastRequestTimes.put( strRemoteAddr, Long.valueOf( lRequestTime ) );
197
198
199 _listOrderedRequests.addFirst( new Entry( strRemoteAddr, lRequestTime ) );
200
201 return true;
202 }
203
204
205
206
207 private void cleanExpiredEntries( )
208 {
209 AppLogService.debug( "DosGuard.class : cleanExpiredEntries()" );
210
211 if ( _listOrderedRequests.size( ) != 0 )
212 {
213
214 long lMinTime = System.currentTimeMillis( ) - _nMinInterval;
215
216 AppLogService.debug( "Min time : " + lMinTime );
217
218
219 boolean bDone = false;
220
221 while ( !bDone && ( _listOrderedRequests.size( ) > 0 ) )
222 {
223
224
225 Entry lastEntry = _listOrderedRequests.getLast( );
226
227 if ( lastEntry.getRequestTime( ) < lMinTime )
228 {
229
230 _mapLastRequestTimes.remove( lastEntry.getRemoteAddr( ) );
231 _listOrderedRequests.removeLast( );
232
233 AppLogService.debug( "Removing [" + lastEntry.getRemoteAddr( ) + ", " +
234 lastEntry.getRequestTime( ) + "]" );
235 }
236 else
237 {
238 bDone = true;
239 }
240 }
241 }
242 }
243
244
245
246
247 private static class Entry
248 {
249 private String _strRemoteAddr;
250 private long _lRequestTime;
251
252
253
254
255
256
257 public Entry( String strRemoteAddr, long lRequestTime )
258 {
259 this._strRemoteAddr = strRemoteAddr;
260 this._lRequestTime = lRequestTime;
261 }
262
263
264
265
266
267 public String getRemoteAddr( )
268 {
269 return _strRemoteAddr;
270 }
271
272
273
274
275
276 public long getRequestTime( )
277 {
278 return _lRequestTime;
279 }
280 }
281 }