Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

this is super beta code. don't use it!

  • Loading branch information...
commit 881edd68294e4155e5294d62eae2c9ca1a821835 1 parent bf92632
@benlucchesi authored
View
12 CookieSessionGrailsPlugin.groovy
@@ -19,6 +19,8 @@
import org.springframework.web.filter.DelegatingFilterProxy
import grails.util.Environment
+import com.granicus.grails.plugins.cookiesession.JavaSessionSerializer
+import com.granicus.grails.plugins.cookiesession.KryoSessionSerializer
import com.granicus.grails.plugins.cookiesession.CookieSessionFilter
import com.granicus.grails.plugins.cookiesession.CookieSessionRepository
import com.granicus.grails.plugins.cookiesession.ExceptionCondenser
@@ -87,6 +89,16 @@ class CookieSessionGrailsPlugin {
if( application.config.grails.plugin.cookiesession.condenseexceptions )
exceptionCondenser(ExceptionCondenser)
+
+ // ALWAYS CONFIGURED!
+ javaSessionSerializer(JavaSessionSerializer){
+ grailsApplication = ref("grailsApplication")
+ }
+
+ if( application.config.grails.plugin.cookiesession.serializer == "kryo" )
+ kryoSessionSerializer(KryoSessionSerializer){
+ grailsApplication = ref("grailsApplication")
+ }
}
}
View
2  grails-app/conf/BuildConfig.groovy
@@ -21,6 +21,8 @@ grails.project.dependency.resolution = {
plugins {
+ build ':spring-security-core:1.2.7.3'
+
build(":release:2.0.4") {
export = false
}
View
136 src/groovy/com/granicus/grails/plugins/cookiesession/CookieSessionRepository.groovy
@@ -20,6 +20,10 @@
package com.granicus.grails.plugins.cookiesession;
import org.springframework.beans.factory.InitializingBean
+import org.springframework.security.core.authority.GrantedAuthorityImpl
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
import java.io.ByteArrayOutputStream;
@@ -36,13 +40,6 @@ import javax.crypto.CipherOutputStream
import javax.crypto.SealedObject
import javax.crypto.Cipher
-import com.esotericsoftware.kryo.Kryo
-import com.esotericsoftware.kryo.io.Input
-import com.esotericsoftware.kryo.io.Output
-import com.esotericsoftware.shaded.org.objenesis.strategy.StdInstantiatorStrategy
-import com.esotericsoftware.kryo.serializers.FieldSerializer
-import de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer
-
import org.codehaus.groovy.grails.web.servlet.GrailsFlashScope
import org.codehaus.groovy.grails.commons.ConfigurationHolder as ch
@@ -51,10 +48,10 @@ import java.util.UUID
import groovy.util.logging.Log4j
@Log4j
-class CookieSessionRepository implements SessionRepository, InitializingBean {
+class CookieSessionRepository implements SessionRepository, InitializingBean, ApplicationContextAware {
def grailsApplication
-
+ ApplicationContext applicationContext
def cryptoKey
String cookieName = "grails_session" // default cookie name
@@ -66,6 +63,8 @@ class CookieSessionRepository implements SessionRepository, InitializingBean {
int maxCookieSize = 2048
String serializer = "java"
+ SessionSerializer sessionSerializer = null
+
void afterPropertiesSet(){
log.trace "afterPropertiesSet()"
@@ -140,19 +139,27 @@ class CookieSessionRepository implements SessionRepository, InitializingBean {
}
if( ch.config.grails.plugin.cookiesession.containsKey('serializer') ){
- if( ! ['java','kryo'].contains( ch.config.grails.plugin.cookiesession.serializer ) ){
- serializer = 'java'
- log.error "grails.plugin.cookiesession.serializer set to invalid value. defaulting to 'java'"
+
+ serializer = ch.config.grails.plugin.cookiesession.serializer
+
+ if( serializer == "java" ){
+ serializer = "javaSessionSerializer"
+ }
+ else if( serializer == "kryo" ){
+ serializer = "kryoSessionSerializer"
+ }
+ else if( applicationContext.containsBean(serializer) && applicationContext.getType(serializer) instanceof SessionSerializer ){
}
else{
- serializer = ch.config.grails.plugin.cookiesession.serializer
- }
+ log.error "no valid serializer configured. defaulting to java"
+ serializer = "javaSessionSerializer"
+ }
log.info "grails.plugin.cookiesession.serializer set: ${serializer}"
}
else{
- serializer = 'java'
- log.info "grails.plugin.cookiesession.serializer not set. defaulting to ${serializer}"
+ serializer = 'javaSessionSerializer'
+ log.info "grails.plugin.cookiesession.serializer not set. defaulting to java."
}
if( ch.config.grails.plugin.cookiesession.containsKey('maxcookiesize') ){
@@ -268,37 +275,30 @@ class CookieSessionRepository implements SessionRepository, InitializingBean {
String serializeSession( SerializableSession session ){
log.trace "serializeSession()"
- log.trace "serializing and compressing session"
+ log.trace "getting sessionSerializer: ${serializer}"
+ def sessionSerializer = applicationContext.getBean(serializer)
+
+ log.trace "serializing session"
+ byte[] bytes = sessionSerializer.serialize(session)
+
+ log.trace "compressing serialiezd session from ${bytes.length} bytes"
ByteArrayOutputStream stream = new ByteArrayOutputStream()
+ def gzipOut = new GZIPOutputStream(stream)
+ gzipOut.write(bytes,0,bytes.length)
+ gzipOut.close()
+
+ bytes = stream.toByteArray()
+ log.trace "compressed serialized session to ${bytes.length}"
- switch( serializer ){
- case 'kryo':
- Kryo kryo = getConfiguredKryoSerializer()
- Output output = new Output(new GZIPOutputStream(stream))
- kryo.writeObject(output,session)
- output.close()
- break
-
- case 'java':
- def output = new ObjectOutputStream(new GZIPOutputStream(stream))
- output.writeObject(session)
- output.close()
- break
- }
-
- byte[] output = null
if( encryptCookie ){
log.trace "encrypting serialized session"
Cipher cipher = Cipher.getInstance(cryptoAlgorithm)
cipher.init( Cipher.ENCRYPT_MODE, cryptoKey )
- output = cipher.doFinal(stream.toByteArray())
- }
- else{
- output = stream.toByteArray()
+ bytes = cipher.doFinal(bytes)
}
- log.trace "base64 encoding serialized session"
- def serializedSession = output.encodeBase64().toString()
+ log.trace "base64 encoding serialized session from ${bytes.length} bytes"
+ def serializedSession = bytes.encodeBase64().toString()
log.info "serialized session: ${serializedSession.size()} bytes"
return serializedSession
@@ -308,44 +308,35 @@ class CookieSessionRepository implements SessionRepository, InitializingBean {
log.trace "deserializeSession()"
def session = null
-
+
try
{
- log.trace "decodeBase64 serialized session"
+ log.trace "decodeBase64 serialized session from ${serializedSession.size()} bytes."
def input = serializedSession.decodeBase64()
-
+
if( encryptCookie ){
- log.trace "decrypting cookie"
+ log.trace "decrypting serialized session from ${input.length} bytes."
Cipher cipher = Cipher.getInstance(cryptoAlgorithm)
cipher.init( Cipher.DECRYPT_MODE, cryptoKey )
input = cipher.doFinal(input)
}
- log.trace "decompressing and deserializing session"
-
- switch( serializer ){
- case 'kryo':
- def inputStream = new Input(new GZIPInputStream( new ByteArrayInputStream( input ) ))
- Kryo kryo = getConfiguredKryoSerializer()
- session = kryo.readObject(inputStream,SerializableSession.class)
- break;
-
- case 'java':
- def inputStream = new ObjectInputStream(new GZIPInputStream( new ByteArrayInputStream( input ) )){
- @Override
- public Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
- //noinspection GroovyUnusedCatchParameter
- try {
- return grailsApplication.classLoader.loadClass(desc.getName())
- } catch (ClassNotFoundException ex) {
- return Class.forName(desc.getName())
- }
- }
- }
-
- session = (SerializableSession)inputStream.readObject();
- break;
+ log.trace "decompressing serialized session from ${input.length} bytes"
+ def inputStream = new GZIPInputStream( new ByteArrayInputStream( input ) )
+ def outputStream = new ByteArrayOutputStream()
+
+ byte[] buffer = new byte[1024]
+ int bytesRead = 0
+ while( (bytesRead = inputStream.read(buffer)) != -1 ){
+ outputStream.write(buffer,0,bytesRead)
}
+ outputStream.flush()
+
+ byte[] bytes = outputStream.toByteArray()
+ log.trace "decompressed serialized session to ${bytes.length} bytes"
+
+ def sessionSerializer = applicationContext.getBean(serializer)
+ session = sessionSerializer.deserialize(bytes)
}
catch( excp ){
log.error "An error occurred while deserializing a session. ${excp}"
@@ -359,17 +350,6 @@ class CookieSessionRepository implements SessionRepository, InitializingBean {
return session
}
- private def getConfiguredKryoSerializer(){
- def kryo = new Kryo()
- def flashScopeSerializer = new FieldSerializer(kryo, GrailsFlashScope.class);
- kryo.register(GrailsFlashScope.class,flashScopeSerializer)
- kryo.register(SerializableSession.class)
- kryo.classLoader = grailsApplication.classLoader
- kryo.instantiatorStrategy = new StdInstantiatorStrategy()
- UnmodifiableCollectionsSerializer.registerSerializers( kryo );
- return kryo
- }
-
private String[] splitString(String input){
log.trace "splitString()"
View
64 src/groovy/com/granicus/grails/plugins/cookiesession/JavaSessionSerializer.groovy
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Ben Lucchesi
+ * ben@granicus.com or benlucchesi@gmail.com
+ */
+
+package com.granicus.grails.plugins.cookiesession;
+
+import org.codehaus.groovy.grails.commons.GrailsApplication
+import groovy.util.logging.Log4j
+
+import java.io.ByteArrayOutputStream;
+
+@Log4j
+class JavaSessionSerializer implements SessionSerializer{
+
+ GrailsApplication grailsApplication
+
+ public byte[] serialize(SerializableSession session){
+ log.trace "serializeSession()"
+ ByteArrayOutputStream stream = new ByteArrayOutputStream()
+ def output = new ObjectOutputStream(stream)
+ output.writeObject(session)
+ output.close()
+ byte[] bytes = stream.toByteArray()
+ log.trace "serialized session. ${bytes.size()} bytes."
+ return bytes
+ }
+
+ public SerializableSession deserialize(byte[] serializedSession){
+
+ log.trace "deserializeSession()"
+
+ def inputStream = new ObjectInputStream(new ByteArrayInputStream( serializedSession )){
+ @Override
+ public Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ //noinspection GroovyUnusedCatchParameter
+ try {
+ return grailsApplication.classLoader.loadClass(desc.getName())
+ } catch (ClassNotFoundException ex) {
+ return Class.forName(desc.getName())
+ }
+ }
+ }
+
+ SerializableSession session = (SerializableSession)inputStream.readObject();
+
+ log.trace "deserialized session."
+ return session
+ }
+}
View
102 src/groovy/com/granicus/grails/plugins/cookiesession/KryoSessionSerializer.groovy
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Ben Lucchesi
+ * ben@granicus.com or benlucchesi@gmail.com
+ */
+
+package com.granicus.grails.plugins.cookiesession;
+
+import org.codehaus.groovy.grails.commons.GrailsApplication
+
+import groovy.util.logging.Log4j
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import com.esotericsoftware.kryo.Kryo
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input
+import com.esotericsoftware.kryo.io.Output
+import com.esotericsoftware.shaded.org.objenesis.strategy.StdInstantiatorStrategy
+import com.esotericsoftware.kryo.serializers.FieldSerializer
+import de.javakaffee.kryoserializers.*
+
+import org.codehaus.groovy.grails.web.servlet.GrailsFlashScope
+
+@Log4j
+class KryoSessionSerializer implements SessionSerializer{
+
+ GrailsApplication grailsApplication
+
+ public byte[] serialize(SerializableSession session){
+ log.trace "serializeSession()"
+ Kryo kryo = getConfiguredKryoSerializer()
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
+ Output output = new Output(outputStream)
+ kryo.writeObject(output,session)
+ output.close()
+ def bytes = outputStream.toByteArray()
+ log.trace "serialized session. ${bytes.size()}"
+ return bytes
+ }
+
+ public SerializableSession deserialize(byte[] serializedSession){
+ log.trace "deserializeSession()"
+ def input = new Input(new ByteArrayInputStream( serializedSession ) )
+ Kryo kryo = getConfiguredKryoSerializer()
+ SerializableSession session = kryo.readObject(input,SerializableSession.class)
+ log.trace "deserialized session."
+ return session
+ }
+
+ private def getConfiguredKryoSerializer(){
+ def kryo = new Kryo()
+
+ // register fieldserializer for GrailsFlashScope
+ def flashScopeSerializer = new FieldSerializer(kryo, GrailsFlashScope.class);
+ kryo.register(GrailsFlashScope.class,flashScopeSerializer)
+
+ //def gais = new GrantedAuthorityImplSerializer()
+ //kryo.register(GrantedAuthorityImpl.class,gais)
+
+ kryo.classLoader = grailsApplication.classLoader
+ kryo.instantiatorStrategy = new StdInstantiatorStrategy()
+
+ //kryo.register( Arrays.asList( "" ).getClass(), new ArraysAsListSerializer( kryo ) );
+ kryo.register( Collections.EMPTY_LIST.getClass(), new CollectionsEmptyListSerializer() );
+ kryo.register( Collections.EMPTY_MAP.getClass(), new CollectionsEmptyMapSerializer() );
+ kryo.register( Collections.EMPTY_SET.getClass(), new CollectionsEmptySetSerializer() );
+ kryo.register( Collections.singletonList( "" ).getClass(), new CollectionsSingletonListSerializer( ) );
+ kryo.register( Collections.singleton( "" ).getClass(), new CollectionsSingletonSetSerializer( ) );
+ kryo.register( Collections.singletonMap( "", "" ).getClass(), new CollectionsSingletonMapSerializer( ) );
+ kryo.register( GregorianCalendar.class, new GregorianCalendarSerializer() );
+ kryo.register( java.lang.reflect.InvocationHandler.class, new JdkProxySerializer( ) );
+ UnmodifiableCollectionsSerializer.registerSerializers( kryo );
+ SynchronizedCollectionsSerializer.registerSerializers( kryo );
+
+ // custom serializers for non-jdk libs
+ // register CGLibProxySerializer, works in combination with the appropriate action in handleUnregisteredClass (see below)
+ //kryo.register( CGLibProxySerializer.CGLibProxyMarker.class, new CGLibProxySerializer( kryo ) );
+ // joda datetime
+ //kryo.register( DateTime.class, new JodaDateTimeSerializer() );
+ // wicket
+ //kryo.register( MiniMap.class, new MiniMapSerializer( kryo ) );
+
+ //UnmodifiableCollectionsSerializer.registerSerializers( kryo );
+
+ return kryo
+ }
+}
View
26 src/groovy/com/granicus/grails/plugins/cookiesession/SessionSerializer.groovy
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Ben Lucchesi
+ * ben@granicus.com or benlucchesi@gmail.com
+ */
+
+package com.granicus.grails.plugins.cookiesession;
+
+public interface SessionSerializer{
+
+ public byte[] serialize(SerializableSession session);
+ public SerializableSession deserialize(byte[] serializedSession);
+}
Please sign in to comment.
Something went wrong with that request. Please try again.