Add setting to throw PageExpiredException when encrypted URL is no longer 
decryptable


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/88ef25b6
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/88ef25b6
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/88ef25b6

Branch: refs/heads/wicket-6.x
Commit: 88ef25b6ab7f94c7e9e4bfe2e5787072f2f7cf89
Parents: 6af2d59
Author: Jesse Long <[email protected]>
Authored: Thu Oct 9 17:32:22 2014 +0200
Committer: Jesse Long <[email protected]>
Committed: Tue Oct 14 22:32:01 2014 +0200

----------------------------------------------------------------------
 .../core/request/mapper/CryptoMapper.java       | 71 +++++++++++++++++++-
 .../core/request/mapper/CryptoMapperTest.java   | 28 ++++++++
 2 files changed, 97 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/88ef25b6/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
 
b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
index 8dde7b1..e626705 100755
--- 
a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
@@ -21,6 +21,7 @@ import java.util.List;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.core.request.handler.RequestSettingRequestHandler;
+import org.apache.wicket.protocol.http.PageExpiredException;
 import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.IRequestMapper;
 import org.apache.wicket.request.Request;
@@ -70,6 +71,12 @@ import org.slf4j.LoggerFactory;
  * When encrypting mounted URLs, we look for the {@link PageComponentInfo} 
parameter, and encrypt only that parameter.
  * </p>
  * 
+ * <p>
+ * {@link CryptoMapper} can be configured to mark encrypted URLs as encrypted, 
and throw a {@link PageExpiredException}
+ * exception if a encrypted URL cannot be decrypted. This can occur when using 
{@code KeyInSessionSubJceCryptFactory}, and
+ * the session has expired.
+ * </p>
+ * 
  * @author igor.vaynberg
  * @author Jesse Long
  * @author svenmeier
@@ -83,10 +90,17 @@ public class CryptoMapper implements IRequestMapperDelegate
         */
        private static final String ENCRYPTED_PAGE_COMPONENT_INFO_PARAMETER = 
"wicket";
 
+       private static final String ENCRYPTED_URL_MARKER_PREFIX = "crypt.";
+
        private final IRequestMapper wrappedMapper;
        private final IProvider<ICrypt> cryptProvider;
 
        /**
+        * Whether or not to mark encrypted URLs as encrypted.
+        */
+       private boolean markEncryptedUrls = false;
+
+       /**
         * Encrypt with {@link ISecuritySettings#getCryptFactory()}.
         * <p>
         * Note: Encryption is done with {@link 
ISecuritySettings#DEFAULT_ENCRYPTION_KEY} if you haven't
@@ -118,6 +132,32 @@ public class CryptoMapper implements IRequestMapperDelegate
        }
 
        /**
+        * Whether or not to mark encrypted URLs as encrypted. If set, a {@link 
PageExpiredException} is thrown when
+        * a encrypted URL can no longer be decrypted.
+        * 
+        * @return whether or not to mark encrypted URLs as encrypted.
+        */
+       public boolean getMarkEncryptedUrls()
+       {
+               return markEncryptedUrls;
+       }
+
+       /**
+        * Sets whether or not to mark encrypted URLs as encrypted. If set, a 
{@link PageExpiredException} is thrown when
+        * a encrypted URL can no longer be decrypted.
+        * 
+        * @param markEncryptedUrls
+        *              whether or not to mark encrypted URLs as encrypted.
+        * 
+        * @return {@code this}, for chaining.
+        */
+       public CryptoMapper setMarkEncryptedUrls(boolean markEncryptedUrls)
+       {
+               this.markEncryptedUrls = markEncryptedUrls;
+               return this;
+       }
+
+       /**
         * {@inheritDoc}
         * <p>
         * This implementation decrypts the URL and passes the decrypted URL to 
the wrapped mapper.
@@ -253,7 +293,15 @@ public class CryptoMapper implements IRequestMapperDelegate
                String encryptedUrlString = 
getCrypt().encryptUrlSafe(url.toString());
 
                Url encryptedUrl = new Url(url.getCharset());
-               encryptedUrl.getSegments().add(encryptedUrlString);
+
+               if (getMarkEncryptedUrls())
+               {
+                       
encryptedUrl.getSegments().add(ENCRYPTED_URL_MARKER_PREFIX + 
encryptedUrlString);
+               }
+               else
+               {
+                       encryptedUrl.getSegments().add(encryptedUrlString);
+               }
 
                int numberOfSegments = url.getSegments().size() - 1;
                HashedSegmentGenerator generator = new 
HashedSegmentGenerator(encryptedUrlString);
@@ -373,6 +421,18 @@ public class CryptoMapper implements IRequestMapperDelegate
                        return null;
                }
 
+               if (getMarkEncryptedUrls())
+               {
+                       if 
(encryptedUrlString.startsWith(ENCRYPTED_URL_MARKER_PREFIX))
+                       {
+                               encryptedUrlString = 
encryptedUrlString.substring(ENCRYPTED_URL_MARKER_PREFIX.length());
+                       }
+                       else
+                       {
+                               return null;
+                       }
+               }
+
                String decryptedUrl;
                try
                {
@@ -386,7 +446,14 @@ public class CryptoMapper implements IRequestMapperDelegate
 
                if (decryptedUrl == null)
                {
-                       return null;
+                       if (getMarkEncryptedUrls())
+                       {
+                               throw new PageExpiredException("Encrypted URL 
is no longer decryptable");
+                       }
+                       else
+                       {
+                               return null;
+                       }
                }
 
                Url originalUrl = Url.parse(decryptedUrl, request.getCharset());

http://git-wip-us.apache.org/repos/asf/wicket/blob/88ef25b6/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/CryptoMapperTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/CryptoMapperTest.java
 
b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/CryptoMapperTest.java
index 8a6181c..b8213e6 100644
--- 
a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/CryptoMapperTest.java
+++ 
b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/CryptoMapperTest.java
@@ -27,6 +27,7 @@ import org.apache.wicket.markup.IMarkupFragment;
 import org.apache.wicket.markup.Markup;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.link.ILinkListener;
+import org.apache.wicket.protocol.http.PageExpiredException;
 import org.apache.wicket.protocol.http.WebApplication;
 import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.IRequestHandlerDelegate;
@@ -573,6 +574,33 @@ public class CryptoMapperTest extends AbstractMapperTest
                        .toString());
        }
 
+       @Test
+       public void markedEncryptedUrlDecrypt()
+       {
+               mapper.setMarkEncryptedUrls(true);
+               Request request = getRequest(Url.parse("crypt." + 
ENCRYPTED_BOOKMARKABLE_URL));
+               IRequestHandler requestHandler = mapper.mapRequest(request);
+
+               assertNotNull(requestHandler);
+               requestHandler = unwrapRequestHandlerDelegate(requestHandler);
+
+               assertTrue(requestHandler instanceof RenderPageRequestHandler);
+
+               RenderPageRequestHandler handler = (RenderPageRequestHandler) 
requestHandler;
+               assertEquals(Page2.class, handler.getPageClass());
+       }
+
+       @Test(expected = PageExpiredException.class)
+       public void expiredMarkedEncryptedUrlThrowsPageExpiredException()
+       {
+               mapper.setMarkEncryptedUrls(true);
+               Url encryptedUrl = mapper.mapHandler(new 
RenderPageRequestHandler(new PageProvider(Page2.class)));
+               
assertTrue(encryptedUrl.getSegments().get(0).startsWith("crypt."));
+               encryptedUrl.getSegments().remove(0);
+               encryptedUrl.getSegments().add(0, "crypt.no decryptable");
+               mapper.mapRequest(getRequest(encryptedUrl));
+       }
+
        private static IRequestHandler 
unwrapRequestHandlerDelegate(IRequestHandler handler)
        {
                while (handler instanceof IRequestHandlerDelegate)

Reply via email to