You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2018/03/08 14:45:02 UTC

knox git commit: KNOX-1190 - Compress cookies set by Pac4J, in some cases the cookie size exceeds 4K and cause them not to set.

Repository: knox
Updated Branches:
  refs/heads/master 9b5665be7 -> 6f4555418


KNOX-1190 - Compress cookies set by Pac4J, in some cases the cookie size exceeds 4K and cause them not to set.


Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/6f455541
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/6f455541
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/6f455541

Branch: refs/heads/master
Commit: 6f45554182d122a39511a6d145d5f99b4cc19c50
Parents: 9b5665b
Author: Sandeep More <mo...@apache.org>
Authored: Thu Mar 8 09:44:56 2018 -0500
Committer: Sandeep More <mo...@apache.org>
Committed: Thu Mar 8 09:44:56 2018 -0500

----------------------------------------------------------------------
 .../pac4j/filter/Pac4jDispatcherFilter.java     | 18 ++++-
 .../gateway/pac4j/session/KnoxSessionStore.java | 73 +++++++++++++++++---
 2 files changed, 82 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/6f455541/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
index 0086228..46186f6 100644
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
@@ -17,6 +17,7 @@
  */
 package org.apache.knox.gateway.pac4j.filter;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 import org.apache.knox.gateway.pac4j.Pac4jMessages;
 import org.apache.knox.gateway.pac4j.session.KnoxSessionStore;
@@ -29,6 +30,8 @@ import org.apache.knox.gateway.services.security.CryptoService;
 import org.pac4j.config.client.PropertiesConfigFactory;
 import org.pac4j.core.client.Client;
 import org.pac4j.core.config.Config;
+import org.pac4j.core.context.session.J2ESessionStore;
+import org.pac4j.core.context.session.SessionStore;
 import org.pac4j.core.util.CommonHelper;
 import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
 import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
@@ -71,6 +74,8 @@ public class Pac4jDispatcherFilter implements Filter {
 
   private static final String PAC4J_CONFIG = "pac4j.config";
 
+  private static final String PAC4J_SESSION_STORE = "pac4j.session.store";
+
   private CallbackFilter callbackFilter;
 
   private SecurityFilter securityFilter;
@@ -160,7 +165,18 @@ public class Pac4jDispatcherFilter implements Filter {
     securityFilter.setConfigOnly(config);
 
     final String domainSuffix = filterConfig.getInitParameter(PAC4J_COOKIE_DOMAIN_SUFFIX_PARAM);
-    config.setSessionStore(new KnoxSessionStore(cryptoService, clusterName, domainSuffix));
+    final String sessionStoreVar = filterConfig.getInitParameter(PAC4J_SESSION_STORE);
+
+    SessionStore sessionStore;
+
+    if(!StringUtils.isBlank(sessionStoreVar) && J2ESessionStore.class.getName().contains(sessionStoreVar) ) {
+      sessionStore = new J2ESessionStore();
+    } else {
+      sessionStore = new KnoxSessionStore(cryptoService, clusterName, domainSuffix);
+    }
+
+    config.setSessionStore(sessionStore);
+
   }
 
   private void addDefaultConfig(String clientNameParameter, Map<String, String> properties) {

http://git-wip-us.apache.org/repos/asf/knox/blob/6f455541/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java
index 4ba55ea..0eb5322 100644
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java
@@ -18,6 +18,7 @@
 package org.apache.knox.gateway.pac4j.session;
 
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
 import org.apache.knox.gateway.services.security.CryptoService;
 import org.apache.knox.gateway.services.security.EncryptionResult;
 import org.apache.knox.gateway.util.Urls;
@@ -30,8 +31,13 @@ import org.pac4j.core.util.JavaSerializationHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.Map;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
 
 /**
  * Specific session store where data are saved into cookies (and not in memory).
@@ -66,7 +72,7 @@ public class KnoxSessionStore implements SessionStore {
         return null;
     }
 
-    private Serializable decryptBase64(final String v) {
+    private Serializable uncompressDecryptBase64(final String v) {
         if (v != null && v.length() > 0) {
             byte[] bytes = Base64.decodeBase64(v);
             EncryptionResult result = EncryptionResult.fromByteArray(bytes);
@@ -76,7 +82,11 @@ public class KnoxSessionStore implements SessionStore {
                     result.iv,
                     result.salt);
             if (clear != null) {
-                return javaSerializationHelper.unserializeFromBytes(clear);
+                try {
+                    return javaSerializationHelper.unserializeFromBytes(unCompress(clear));
+                } catch (IOException e) {
+                    throw new TechnicalException(e);
+                }
             }
         }
         return null;
@@ -86,18 +96,31 @@ public class KnoxSessionStore implements SessionStore {
         final Cookie cookie = ContextHelper.getCookie(context, PAC4J_SESSION_PREFIX + key);
         Object value = null;
         if (cookie != null) {
-            value = decryptBase64(cookie.getValue());
+            value = uncompressDecryptBase64(cookie.getValue());
         }
         logger.debug("Get from session: {} = {}", key, value);
         return value;
     }
 
-    private String encryptBase64(final Object o) {
+    private String compressEncryptBase64(final Object o) {
         if (o == null || o.equals("")
             || (o instanceof Map<?,?> && ((Map<?,?>)o).isEmpty())) {
             return null;
         } else {
-            final byte[] bytes = javaSerializationHelper.serializeToBytes((Serializable) o);
+            byte[] bytes = javaSerializationHelper.serializeToBytes((Serializable) o);
+
+            /* compress the data  */
+            try {
+                bytes = compress(bytes);
+
+                if(bytes.length > 3000) {
+                    logger.warn("Cookie too big, it might not be properly set");
+                }
+
+            } catch (final IOException e) {
+                throw new TechnicalException(e);
+            }
+
             EncryptionResult result = cryptoService.encryptForCluster(this.clusterName, PAC4J_PASSWORD, bytes);
             return Base64.encodeBase64String(result.toByteAray());
         }
@@ -105,7 +128,7 @@ public class KnoxSessionStore implements SessionStore {
 
     public void set(WebContext context, String key, Object value) {
         logger.debug("Save in session: {} = {}", key, value);
-        final Cookie cookie = new Cookie(PAC4J_SESSION_PREFIX + key, encryptBase64(value));
+        final Cookie cookie = new Cookie(PAC4J_SESSION_PREFIX + key, compressEncryptBase64(value));
         try {
             String domain = Urls.getDomainName(context.getFullRequestURL(), this.domainSuffix);
             if (domain == null) {
@@ -120,6 +143,41 @@ public class KnoxSessionStore implements SessionStore {
         context.addResponseCookie(cookie);
     }
 
+    /**
+     * A function used to compress the data using GZIP
+     * @param data
+     * @return gziped data
+     * @since 1.1.0
+     */
+    private static byte[] compress(final byte[] data) throws IOException {
+
+        try (final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(
+            data.length);
+            final GZIPOutputStream gzip = new GZIPOutputStream(byteStream)) {
+            gzip.write(data);
+            gzip.close();
+            return byteStream.toByteArray();
+        }
+    }
+
+    /**
+     * Decompress the data compressed using gzip
+     *
+     * @param data
+     * @return uncompressed data
+     * @throws IOException
+     * @since 1.1.0
+     */
+    private static byte[] unCompress(final byte[] data) throws IOException {
+
+        try (final ByteArrayInputStream inputStream = new ByteArrayInputStream(
+            data);
+            final GZIPInputStream gzip = new GZIPInputStream(inputStream)) {
+            return IOUtils.toByteArray(gzip);
+        }
+    }
+
+
     @Override
     public SessionStore buildFromTrackableSession(WebContext arg0, Object arg1) {
         // TODO Auto-generated method stub
@@ -139,8 +197,7 @@ public class KnoxSessionStore implements SessionStore {
     }
 
     @Override
-    public boolean renewSession(WebContext arg0) {
-        // TODO Auto-generated method stub
+    public boolean renewSession(final WebContext context) {
         return false;
     }
 }