Make the CSRF nonce cache serializable to fix an issue reported on the users list.
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 21 Mar 2011 22:08:47 +0000 (22:08 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 21 Mar 2011 22:08:47 +0000 (22:08 +0000)
Custom serialization code could shave ~20% but the code isn't as clean.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1083987 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/filters/CsrfPreventionFilter.java
test/org/apache/catalina/filters/TestCsrfPreventionFilter.java
webapps/docs/changelog.xml

index 7151907..0189632 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.catalina.filters;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.security.SecureRandom;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -287,7 +288,9 @@ public class CsrfPreventionFilter extends FilterBase {
         }
     }
     
-    private static class LruCache<T> {
+    protected static class LruCache<T> implements Serializable {
+
+        private static final long serialVersionUID = 1L;
 
         // Although the internal implementation uses a Map, this cache
         // implementation is only concerned with the keys.
index 46ebe5a..92f8905 100644 (file)
 
 package org.apache.catalina.filters;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.catalina.filters.CsrfPreventionFilter.LruCache;
 import org.apache.catalina.startup.TomcatBaseTest;
 
 public class TestCsrfPreventionFilter extends TomcatBaseTest {
@@ -50,6 +56,41 @@ public class TestCsrfPreventionFilter extends TomcatBaseTest {
                 wrapper.encodeRedirectURL("/test?a=b#c"));
     }
     
+    public void testLruCacheSerializable() throws Exception {
+        LruCache<String> cache = new LruCache<String>(5);
+        cache.add("key1");
+        cache.add("key2");
+        cache.add("key3");
+        cache.add("key4");
+        cache.add("key5");
+        cache.add("key6");
+        
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(baos);
+        oos.writeObject(cache);
+        
+        ByteArrayInputStream bais =
+            new ByteArrayInputStream(baos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        @SuppressWarnings("unchecked")
+        LruCache<String> cache2 = (LruCache<String>) ois.readObject();
+        
+        cache2.add("key7");
+        assertFalse(cache2.contains("key1"));
+        assertFalse(cache2.contains("key2"));
+        assertTrue(cache2.contains("key3"));
+        assertTrue(cache2.contains("key4"));
+        assertTrue(cache2.contains("key5"));
+        assertTrue(cache2.contains("key6"));
+        assertTrue(cache2.contains("key7"));
+    }
+
+    public void testLruCacheSerializablePerformance() throws Exception {
+        for (int i = 0; i < 10000; i++) {
+            testLruCacheSerializable();
+        }
+    }
+
     private static class NonEncodingResponse extends TesterResponse {
 
         @Override
index b51b83f..3dca028 100644 (file)
         <bug>50929</bug>: When wrapping an exception, include the root cause.
         Patch provided by sebb. (markt) 
       </fix>
+      <fix>
+        Make the CSRF nonce cache serializable so that it can be replicated
+        across a cluster and/or persisted across Tomcat restarts. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">