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

Mutable rich session objects don't work with session's saveDelta() #177

Open
brentonr opened this issue Mar 25, 2015 · 11 comments
Open

Mutable rich session objects don't work with session's saveDelta() #177

brentonr opened this issue Mar 25, 2015 · 11 comments
Assignees
Labels
status: waiting-for-triage An issue we've not yet triaged

Comments

@brentonr
Copy link

When a mutable object is referenced in a fetched session, and that object is modified, the attribute is never put into the delta list for saving to redis.

This was observed using spring-session with spring-security-oauth2, specifically with org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint and it's @SessionAttrtibutes("authorizationRequest") annotation. While the authorizationRequest object (map in this case) is modified, the attribute "authorizationRequest" is not entered into the delta. On a subsequent POST, the request is unauthorized because the authorizationRequest map is not up to date in the session.

@AndreasKl
Copy link

@brentonr storing mutable data in a session is considered bad practice and leads to hard to track issues. Implementing some sort of dirty tracking via proxies would be possible but wouldn`t solve all inherent problems that mutable state in a session causes.

There is a nice read why mutable state in a session is an issue:
http://www.ibm.com/developerworks/library/j-jtp09238/

@rwinch
Copy link
Member

rwinch commented Apr 15, 2015

@brentonr This is expected behavior and is the same when using a container's distributed sessions (i.e. Tomcat can persist sessions to a database. If you want this functionality, you could implement SessionRepository yourself using something that is returning proxied objects. For example, you might implement the store using JPA.

@brentonr
Copy link
Author

@AndreasKl I agree totally. @rwinch I was hoping there was something simpler that was available where I could use spring-session with spring-security-oauth2 "out of the box". Thanks to both of you for your feedback.

@rwinch
Copy link
Member

rwinch commented Apr 15, 2015

@brentonr Thanks for your response.

If there is something that is preventing spring-security-oauth2 from working we can and should certainly make that happen out of the box. I just don't think that this is the correct way of doing it. Please make a more specific issue stating the problem (perhaps providing a sample too).

@rwinch rwinch self-assigned this Apr 15, 2015
@brentonr
Copy link
Author

I haven't looked at the 1.0.1 release yet to see if it somehow changes things, but I was using spring-security-oauth2 with spring-session-1.0.0.

The problem is in org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint, with the use of the authorizationRequest object - it's a rich object that is mapped to the session map with the @SessionAttributes("authorizationRequest") attribute on that class.

Because the RequestMapping controllers in AuthorizationEndpoint mutate the state of authorizationRequest, it's never updated in the RedisSession delta attributes to be saved (because RedisSession only updates the delta attributes when set again on the session's map entries, not on update of any rich objects contained in that map entry).

Thus, it seems all modifications get lost between requests. I've worked around it by re-setting all present attributes in the session in a filter, but I'd be happy to try any suggestions.

@rwinch
Copy link
Member

rwinch commented Apr 16, 2015

@brentonr I think your problem seems to be similar to #52 Can you try the advise there?

@brentonr
Copy link
Author

FWIW, I didn't explicitly call this out in previous comments, but this seems to only be a problem with RedisSession and not with Tomcat's JDBCStore (as previously intimated/referenced). Tomcat's JDBCStore works because it serializes the entire session map (and its objects) on each save.

RedisSession will only save those attributes set during the lifetime of the object (i.e. those entries in the delta map). Because the authorizationRequest map entry isn't set with setAttribute, only mutated "in-place" on the loaded RedisSession, RedisSession doesn't attempt to save it.

@rwinch
Copy link
Member

rwinch commented Apr 17, 2015

Thanks for bringing this to my attention.

This doesn't align with the way I recall things working in the past. Perhaps things have changed or (more likely) my memory is poor.

The problem with saving every attribute on every request can have a pretty significant impact on performance. I suppose we could look into providing a flag to save every attribute every time.

Thanks again for the feedback. I'll reopen this to look into other options and further investigate how other implementations work.

@rwinch rwinch reopened this Apr 17, 2015
@btpka3
Copy link

btpka3 commented Oct 30, 2015

Not every library would :

  1. session#setAttribute(String)
  2. modify the attribute object,
  3. then invoke session#setAttribute(String, Object) to save it again.

I don't think this is "spring-session"'s fault. But provide some fix in "spring-session" would be most convenient (We could not wait every 3rd library to fix it)。What about this suggestion :

Modify RedisOperationsSessionRepository to provide a switch (system property? or add some APIs), this switch enable different delta saving method:

  1. (current implemention) save every attribute which had invoked session#setAttribute(String, Object), session#removeAttribute(String)
  2. plus : save every attribute which had invoked session#getAttribute(String)
  3. save every attribute:
    1. loop session#getAttributeNames(),
    2. retrieve attribute object from local cache or remote redis storage,
    3. then save them all again

I think the second way would fix most situation.
Performance is important, but do correct thing is more important, isn't it?

@LaiZhou
Copy link

LaiZhou commented Jul 17, 2016

Did version 1.2.0-Release fix this problem, I'm also wating for a new version to solve the problem

@sudokai
Copy link

sudokai commented May 15, 2017

Any update on this? I have taken a look at the implementation of RedisOperationsSessionRepository and only explicit calls to setAttribute will trigger an attribute to be saved again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

7 participants