Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialized session exceeds maximum session size that can be stored in cookies. Max size: 8000, Requested Session Size: 11008. #59

Open
priyanka83 opened this issue Jun 30, 2015 · 21 comments

Comments

@priyanka83
Copy link

We are using cookie session plugin in our application with spring security enabled . Seems like there is some unwanted data being stored in session which is causing the session size to increase dramatically. I have tried all of the above suggestions, bumping the number of cookies to 4 and increasing the header size and cookie session timeout. When increasing the number of cookies to 4 , it is having some issues when we try to logout /login. The exception we see is :
ERROR cookiesession.CookieSessionRepository - cause: null
java.lang.RuntimeException: = character not at end of base64 value.

Also we are seeing exceptions when it tries to deserialize the session and throws some gzip related to exceptions

This is the setting we have on config groovy:

grails.plugin.cookiesession.enabled = true
grails.plugin.cookiesession.encryptcookie = true
grails.plugin.cookiesession.cryptoalgorithm = "AES"
grails.plugin.cookiesession.secret = cookieSecret
grails.plugin.cookiesession.cookiecount = 1
grails.plugin.cookiesession.maxcookiesize = 8000
grails.plugin.cookiesession.sessiontimeout = 3600
grails.plugin.cookiesession.cookiename = 'gsession'
grails.plugin.cookiesession.condenseexceptions = true
grails.plugin.cookiesession.springsecuritycompatibility = true

Any help will be appreciated as this is causing too much havoc on our producion environment. The application is hosted on jboss 6.1 EAP.

@benlucchesi
Copy link
Owner

  1. have you upgraded to latest version
  2. does the problem start happening after fail logins and redirects?

On Tue, Jun 30, 2015, 2:14 PM priyanka83 [email protected] wrote:

We are using cookie session plugin in our application with spring security
enabled . Seems like there is some unwanted data being stored in session
which is causing the session size to increase dramatically. I have tried
all of the above suggestions, bumping the number of cookies to 4 and
increasing the header size and cookie session timeout. When increasing the
number of cookies to 4 , it is having some issues when we try to logout
/login. The exception we see is :
ERROR cookiesession.CookieSessionRepository - cause: null
java.lang.RuntimeException: = character not at end of base64 value.

Also we are seeing exceptions when it tries to deserialize the session and
throws some gzip related to exceptions

This is the setting we have on config groovy:

grails.plugin.cookiesession.enabled = true
grails.plugin.cookiesession.encryptcookie = true
grails.plugin.cookiesession.cryptoalgorithm = "AES"
grails.plugin.cookiesession.secret = cookieSecret
grails.plugin.cookiesession.cookiecount = 1
grails.plugin.cookiesession.maxcookiesize = 8000
grails.plugin.cookiesession.sessiontimeout = 3600
grails.plugin.cookiesession.cookiename = 'gsession'
grails.plugin.cookiesession.condenseexceptions = true
grails.plugin.cookiesession.springsecuritycompatibility = true

Any help will be appreciated as this is causing too much havoc on our
producion environment. The application is hosted on jboss 6.1 EAP.


Reply to this email directly or view it on GitHub
#59.

@priyanka83
Copy link
Author

@benlucchesi : We have upgraded the cookie session plugin to the latest version and testing it out at present. The problem was intermittent and usually happening after redirects. We dint see any failed login attempts on the production logs. Will keep you posted. Thanks for the prompt response.

@benlucchesi
Copy link
Owner

If spring security is redirecting from a controller action due to lack of
permission, spring security stuffs a copy of the request including a copy
of the session. this is what causes it to explode in size. The latest
version of the plugin removes the session the saved request to prevent this
behavior.

On Wed, Jul 1, 2015, 12:19 PM priyanka83 [email protected] wrote:

@benlucchesi https://github.com/benlucchesi : We have upgraded the
cookie session plugin to the latest version and testing it out at present.
The problem was intermittent and usually happening after redirects. We dint
see any failed login attempts on the production logs. Will keep you posted.
Thanks for the prompt response.


Reply to this email directly or view it on GitHub
#59 (comment)
.

@priyanka83
Copy link
Author

@benlucchesi : we upgraded the plugin version and deployed to our production environment and we are not seeing any serialized session increase exceptions. Thank you very much for your help! :)

@denis111
Copy link
Contributor

denis111 commented Sep 2, 2015

For me the problem is still persists. I see that cookies are deleted from SPRING_SECURITY_SAVED_REQUEST but then after the session gets serialized to bytes by kryo that bytes still contain gsession things!! It's easy to proove. Put a breakpoint at the end of serialize method of KryoSessionSerializer. And evaluate such expression in your ide:

new File('session.txt').withOutputStream {
it.write bytes
}

Then open session.txt with text editor and you'll see all the cookies there. That's very strange because when you deserialize it there's no gsession cookies. I don't know how it's possible.

@benlucchesi
Copy link
Owner

That is very strange. To start with, what version of grails, spring
security plugin, and cookie session are you using?

On Wed, Sep 2, 2015 at 7:30 AM, denis111 [email protected] wrote:

For me the problem is still persists. I see that cookies are deleted from
SPRING_SECURITY_SAVED_REQUEST but then after the session gets serialized to
bytes by kryo that bytes still contain gsession things!! It's easy to
proove. Put a breakpoint at the end of serialize method of
KryoSessionSerializer. And evaluate such expression in your ide:

new File('session.txt').withOutputStream {
it.write bytes
}

Then open session.txt with text editor and you'll see all the cookies
there. That's very strange because when you deserialize it there's no
gsession cookies. I don't know how it's possible.


Reply to this email directly or view it on GitHub
#59 (comment)
.

@denis111
Copy link
Contributor

denis111 commented Sep 3, 2015

Grails 2.5.1 , spring-security-core:2.0-RC5, cookie-session:2.0.18.
I don't know how it's possible, maybe java bug or kryo or spring. java oracle jdk build 1.7.0_79-b15

Saved session in txt looks like:

ava.util.HashMa���SPRING_SECURITY_CONTEX‘��org.springframework.security.core.context.SecurityContextImpÏ���org.codehaus.groovy.grails.FLASH_SCOP≈ ���java.util.concurrent.ConcurrentHashMa�������SPRING_SECURITY_SAVED_REQUES‘��¬�org.springframework.security.web.savedrequest.DefaultSavedRequest��/immogeÔ��java.util.ArrayLisÙ����org.springframework.security.web.savedrequest.SavedCookiÂ�����wasHerÂ���Ç1��������userI‰���bb80e016-7836-3124-8cca-a8fa8120933Â���java.util.TreeMa���java.lang.String$CaseInsensitiveComparatoÚ���accepÙ������text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.∏�accept-encodinÁ������gzip, deflatÂ�accept-languagÂ������es-ES,es;q=0.8,en-US;q=0.5,en;q=0.≥�cache-controÏ������max-age=∞�connectioÓ������keep-alivÂ�cookiÂ������ÒnwasHere=1; userId=bb80e016-7836-3124-8cca-a8fa8120933e; gsession-0=CK6zIAEXnf885hnozwUlZav5J/alofXZv5c6B/I8JY99YzMuZFnXPOXPFz56+zSfcyoLQlsY61K5tNvIKcB3YPcNS1rSi6Bi0Fwf4jnH4w7xTR0FTQVBulcaWKPoJyU5Pspyfzs1/N1cokbjWcL2aDxEmBObWfKsBRMSXUg2OEuT2PJdegMFwaK3kcdJ7jQzaHarvh9N00n0SiNs6kBsYvg9kxmwNNJz8BMx97ClcY7PmdBZ/In4Iyxy0aRvLXFZkT6dY9JpuCKVt/O90GU4Q3kWJ9NrJMW89iRGbW72uFn1utUwYAKz2d8LtveT5hrBLvtCxfH3DqKFJmkIOv0t6Vho7/0Mq/ko/lf/YYoADdQuZ27lTCRFDw8QIbnDLyo0ZPAvlVxivpkMkVi8XP3vR/YIZnTsMqoIVBqgjM51p9HcLBQhrvy7OYDaerBIOWzuB/..... and so on.

@benlucchesi
Copy link
Owner

hey denis111,

I don't see how this can be a bug in the serializer - its not going to manufacture cookies in the saved request in the session.

I don't know what actions are being performed in your app prior to the session being serialized, but could put a breakpoint the src/groovy/com/granicus/grails/plugins/cookiesession/SecurityContextSessionPersistenceListener.groovy and verify the session.SPRING_SECURITY_SAVED_REQUEST.cookies collection is being iterated over and that cookies are being removed. after everything is removed, can you then inspect the session.SPRING_SECURITY_SAVED_REQUEST in your debugger and verify nothing is left over.

Also, can you try clearing all cookies from your browser or use an incognito mode so that you get a fresh session and then try to repro the error. It could be that your browser is sending up a bad session that always results in a redirect. If you clear cookies and you aren't able to recreate, then its likely that bad cookies were stuck in the browser.

also, can you post your cookie session config settings (don't include your cookie session encryption key)

If you have any other details about the scenario, that would help too - redirects, etc.

@denis111
Copy link
Contributor

denis111 commented Sep 9, 2015

I started th browser in private mode. And tried to access a protected controller (/admin) few times to provoke redirects to login screen to see how saved session grows, here's the screenshot
gsession

And here's my config:
grails.plugin.cookiesession.enabled = true
grails.plugin.cookiesession.encryptcookie = true
grails.plugin.cookiesession.cryptoalgorithm = 'Blowfish/CBC/PKCS5Padding'
grails.plugin.cookiesession.secret = 'noooooo'
grails.plugin.cookiesession.serializer = 'kryo'
grails.plugin.cookiesession.springsecuritycompatibility = true
grails.plugin.cookiesession.cookiecount = 10

@kys30
Copy link

kys30 commented Sep 28, 2015

Hi benlucchesi ,

We are also facing a similar issue with our application.

We are using Grails 2.3.2 with Spring security - 2.0RC2 and Cookiesession 2.0.16.

  1. With java serializer, the cookie size increases very rapidly with every failed login attempt.
  2. Also, we are not getting redirected to the correct url after signing in (it gets redirected to the default URL). I think this problem is arising due to SPRING_SECURITY_SAVED_REQUEST. Just to keep the size in check, I tried to flush out session.SPRING_SECURITY_SAVED_REQUEST after in login/auth. In this case, I am able to restrict the cookie size (1033Kb, which is also a bit high) but again, loose all the saved request information.
  3. Using kryo serializer is decreasing the cookie size but it gives a lot of intermittent authentication issues.

Do we have any work around over this.

Thanks,
Kaushik

@benlucchesi
Copy link
Owner

Kaushik,

thanks for the feed back on this. I've gotten a couple of reports regarding
session sizes increasing even though the SPRING_SECURITY_SAVED_REQUEST is
getting cleared out.

I've just finished upgrading the plugin to grails 3.0 and I've got a
working branch with upgrades kryo to latest version. As I work through
issues with that branch, I'll see if I can get to the root cause of this.

-ben

On Mon, Sep 28, 2015 at 9:54 AM, Kaushik Shelat [email protected]
wrote:

Hi benlucchesi ,

We are also facing a similar issue with our application.

We are using Grails 2.3.2 with Spring security - 2.0RC2 and Cookiesession
2.0.16.

With java serializer, the cookie size increases very rapidly with
every failed login attempt.
2.

Also, we are not getting redirected to the correct url after signing
in (it gets redirected to the default URL). I think this problem is arising
due to SPRING_SECURITY_SAVED_REQUEST. Just to keep the size in check, I
tried to flush out session.SPRING_SECURITY_SAVED_REQUEST after in
login/auth. In this case, I am able to restrict the cookie size (1033Kb,
which is also a bit high) but again, loose all the saved request
information.
3.

Using kryo serializer is decreasing the cookie size but it gives a lot
of intermittent authentication issues.

Do we have any work around over this.

Thanks,
Kaushik


Reply to this email directly or view it on GitHub
#59 (comment)
.

@benlucchesi
Copy link
Owner

Guys, I've been trying to repro the issue by failing log in attempts and I can't get the session to explode.

Try something for me though.... add this setting and test out your scenario:

grails.plugin.cookiesession.condenseexceptions = true

exceptions are notoriously unhealthy for serializers and cookie-sessions. If an exception gets stuffed into the session, it ends up taking a ton of data into the session, possibly including references to the request which contained the cookie. If this happened, it would explain why cookies keep reappearing in the session even though the saved request gets cleared out.

Please try this and let me know how it works.

-ben

@denis111
Copy link
Contributor

denis111 commented Oct 5, 2015

Should the same config option work for 2.0.18? (seems not or just not solves the problem)

@benlucchesi
Copy link
Owner

the condenseexceptions option does work for 2.0.18, however, I was finally able to repro the issue and condenseexceptions didn't help. I'm working on root cause now...

@benlucchesi
Copy link
Owner

Guys, I haven't found the root cause of the issue, but I have a work around until I do. The strategy is as follows:

  1. remove the exception translation filter from spring security. this is the object responsible for storing the current request into the session and the redirecting the browser to the login page
  2. add a custom url mapping for 500 on spring authentication exceptions and map it to an error handler controller. The handler will function as the access denied handler and redirect to the login page.
  3. in the error handler method, save the forward uri and redirect to a custom login page with the forward uri on the query string
  4. in the controller method that renders the login page, pass the forward-uri that came from the access denied handler into a hidden input with the name "spring-security-redirect" in the login form. Spring will pick up this field and perform the redirect for you after a successful login.

To remove the exception translation filter, add this to the Config.groovy
grails.plugin.springsecurity.filterChain.filterNames = [
'securityContextPersistenceFilter', 'logoutFilter', 'authenticationProcessingFilter',
'rememberMeAuthenticationFilter', 'anonymousAuthenticationFilter', 'filterInvocationInterceptor' ]
// filter list sans exceptionTranslationFilter

add this mapping to your URLMappings.groovy
"500"(controller: "errors", action: "accessDenied",
exception: org.springframework.security.access.AccessDeniedException)

If you don't have an ErrorsController.groovy, create one and add this method:
def accessDenied(){
redirect uri: "/index/login?redirecturl=${forward}"
}
replace the uri with your login page

In your login page render the redirecturl into the form as follows:

the spring-security-redirect is a special form param picked up by the authentication handler and performs the redirect.

Based on my experiments, this method seem to be a good work around and drastically reduces the size of the serialized session.

Please let me know if this is successful for you.

-ben

@denis111
Copy link
Contributor

That's seems to work for now! But just how do i supress exception message in the output log?

@kys30
Copy link

kys30 commented Oct 16, 2015

Thanks Ben. This worked for me too.

Though, I still have a concern with my cookie size. After removing the SAVED REQUEST from session, the cookie size comes around 1500b .

I see many websites (Ex: Facebook and Linkedin ) where the session cookies, which might be storing much more information are very small in size. !

Using kryo does reduces my cookie size to almost half but the serializer doesn't work for me (as you have mentioned in the docs) !

Thanks for the help
-Kaushik

@denis111
Copy link
Contributor

Facebook definately doesn't use any generic session of any generic server/framework and has some custom implementation to store it's certain things, I think.

But about the size and serialization. Does any (de)compression applied to the cookie before saving/reading it? If not then maybe some fast algorythm wouldn't impact much the server performance? Like snappy or what is the latest fastest compressor exists...

@benlucchesi
Copy link
Owner

Guys,

I'm really glad to hear things are working with the fix.

Firstly, the cookie-session plugin has integrated compression. Check your
settings and make sure its turned on.

Secondly, don't just shove anything into a session. Instead of storing
entire objects, just store the essential elements of what you need. If you
assign objects that aren't yours to the session, you won't know exactly
what's in that object's graph when it gets serialized and it could be
massive. Consider Exceptions - depending on how its written it may have the
stack trace along references to a myriad of other objects. That's why I
wrote the exception condenser - it reduces exceptions to just the string
message of the exception. If you have the choice of storing an object in a
session vs storing the ID of an object in a session, then just store the ID
and retrieve the object when you need it.

Finally, always try to use the kryo serializer - it gives you far more
control over the serialization process, is quicker and produces smaller
results than the java serializer. The advantage of the java serializer is
that it can serialize and deserialize objects that the kryo serializer
can't (unless you tell kryo to use the java serializer for those object).
If you know what objects break the kryo serializer, then write a custom
serializer for those objects - there's an API for handling that situation
in the plugin, check the docs. Alternatively, follow my prior advice and
just store elements of the object that break kryo.

Regarding facebook or other apps and cookies session - consider for a
moment what they would need to store. Identity? That can be as little as a
unique ID for looking up the user or as sophisticated as the the principal
and roles as with spring security. In any case, the reason that sessions
are encrypted at the server (as does the cookie-session plugin) is to
conceal the contents from the user and to prevent tampering so that it
doesn't become an attack vector on the server.... you can guess what's in a
cookie session, you can inspect the cookie session, tamper with it, etc.
but if the app developer has done their job, then you won't get very far.

FYI - I've got a working version that upgrades the kryo serializer to the
latest version. I should have that out in the next couple of weeks.

-ben

On Fri, Oct 16, 2015 at 4:22 AM, denis111 [email protected] wrote:

Facebook definately doesn't use any generic session of any generic
server/framework and has some custom implementation to store it's certain
things, I think.

But about the size and serialization. Does any (de)compression applied to
the cookie before saving/reading it? If not then maybe some fast algorythm
wouldn't impact much the server performance? Like snappy or what is the
latest fastest compressor exists...


Reply to this email directly or view it on GitHub
#59 (comment)
.

@denis111
Copy link
Contributor

Great news, waiting for updated kryo!. About compression: yes, i see gzip in source code but just wanted to mention that there's also fater algorythms that maybe some users might like for server performance (like lz4 one): http://java-performance.info/performance-general-compression/

@double16
Copy link

May be fixed in https://github.com/double16/grails-cookie-session/tree/release/4.0.0
Session is much smaller now with kryo 4 and several kryo serializers made for spring security classes.

dependencies {
compile 'org.grails.plugins:cookie-session:4.0.0.RC1'
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants