On Sep 17, 2014, at 20:03 , Mike Orr <[email protected]> wrote: > Previously we've discussed the assumptions in Pyramid's ISession and > Session code and in 'pyramid_redis_sessions'. I complained that > pickled sessions are hard to monitor in aggregate in the backend, > because you have to deserialize each one in Python to query a > property, or visually interpret the Pickle protocol. I tried JSON > serialization under pyramid_redis_sessions, and it works and is more > readable, but still not ideal because it escapes quotes in the JSON > like Python's repr().
The thing is that Pyramid’s session API makes the guarantee that as long as your object can be pickled, you can store it in the session. If you are willing to break that guarantee, it is perfectly fine to do so. For most apps I’d dare say this won’t even be an issue since they don’t tend to store stuff in the session that has a requirement that it be pickled. > > I'm now considering another idea, of keeping the traditional session > ID cookie but storing the session variables in individual Redis keys, > allowing all Redis datatypes and operations, and making the caller > responsible for any JSON serializing of individual session variables. > I think I'll have to bypass most of 'pyramid.session' because it and > all the third-party adapters really, really, really wants to serialize > the session to a string and makes it hard not to. I'm not sure I > necessarily need the 'request.session' API, just some convenient way > to get the values. Why bypass it? Write your own implementation of the Pyramid session machinery and instead of serializing it into a string en-masse, instead have each key in the dictionary be an item in redis directly tied to a certain session id. Now you can continue to use request.session as you wish, and everything is copacetic, and you can switch out existing session backends with other ones as needed. > > What I don't want to write is the session ID generation, os.urandom(20), turned into hex… https://github.com/usingnamespace/pyramid_pluggable_session/blob/master/pyramid_pluggable_session/__init__.py#L335 > cookie, > and > signing code. webob.cookies.SignedCookieProfile > That sounds like the same code Pyramid's AuthTicket > class replicates, so I'm wondering if I can piggyback on the auth > ticket as a session ID. (That will work in my current application > which has authentication. It won't work in my other applications which > don't, but I can cross that bridge when I get to it.) Why? authentication is different from sessions. Two different cookies would be highly preferred, they have different lifetimes, different use cases, and tying it to AuthTicket means you are stuck with it and won’t be able to swap it out for a different authentication provider if the need arises. > I'm not sure if > I can get the auth ticket ID in views, but if I can then everything > else should fall into place. > > Does this sound like a viable idea or are there any technical or > security gotchas I should be aware of. > > If this doesn't work and I have to make my own session ID cookie, what > do I need to keep in mind? I hear people talk about signing session > cookies and tying the session to the client's IP. Is there anything > else I should tie it to? webob.cookies.SignedCookieProfile: https://github.com/Pylons/webob/blob/master/webob/cookies.py#L749 Don’t tie it to the clients IP, you will come to regret it when your clients end up talking IPv6 with privacy addresses that change, or if they move from work to home with a laptop for instance, or are behind a corporate proxy that does load balancing across different outgoing IP's (I ran into this recently … that was a lot of fun!) For example, in my pyramid_pluggable_session this is how I deal with the cookie: Create the cookie helper: https://github.com/usingnamespace/pyramid_pluggable_session/blob/master/pyramid_pluggable_session/__init__.py#L170-180 Fetch a value from the cookie: https://github.com/usingnamespace/pyramid_pluggable_session/blob/master/pyramid_pluggable_session/__init__.py#L197 Save a value to the cookie: https://github.com/usingnamespace/pyramid_pluggable_session/blob/master/pyramid_pluggable_session/__init__.py#L331 These operations automatically do the following: 1. Create a helper 2. Bind to a request, fetch a value, this includes checking to see if it is properly signed, and deserialising the original value stored, if not properly signed, returns None 3. Save a value, this includes serialising it, and signing it, and automatically adding it as a cookie to the response The rest of the code is around dealing with session expiration… and with figuring out when the session has changed so that the session has to be saved. If you take my existing code, change https://github.com/usingnamespace/pyramid_pluggable_session/blob/master/pyramid_pluggable_session/__init__.py#L324-330 to instead of serialising it send the dictionary wholesale to the backend, you’d be able to do what you proposed fairly easily. > > -- > Mike Orr <[email protected]> > Cheers, Bert JW Regeer
smime.p7s
Description: S/MIME cryptographic signature
