What are good ways to create a HTTP session with simultaneous requests? - python

I have a problem and can't solve it. Maybe I'm making it too hard or complex or I'm just going in the wrong direction and thinking of things that don't make sense. Below is a description of what happens. (Multiple tabs opened in a browser or a page that requests some other pages at the same time for example.)
I have a situation where 3 requests are received by the web application simultaneously and new user session has to be created. This session is used to store notification, XSRF token and login information when the user logs in. The application uses threads to handle requests (CherryPy under Bottle.py).
The 3 threads (or processes in case or multiple application instances) start handling the 3 requests. They check the cookie, no session exists, and create a new unique token that is stored in a cookie and in Redis. This will all happen at the same time and they don't know if a session already has been created by another thread, because all 3 tokens are unique.
These unused sessions will expire eventually, but it's not neat. It means everytime a client simultaneously does N requests and a new session needs to be created, N-1 session are useless.
If there is a property that can be used to identify a client, like an IP address, it would be a lot easier, but an IP address is not safe to use in this case. This property can be used to atomically store a session in Redis and other requests would just pick up that session.

If this is through a browser and is using cookies then this shouldn't be an issue at all. The cookie will, from what I can tell, the last session value that it is set to. If the client you are using does not use cookies then of course it will open a new session for each connection.

Related

If Pyramid sessions are one-way hashed and not stored server-side, where is the data coming from?

When using the SignedCookieSessionFactory, the documentation states that the sha512 HMAC digest algorithm is used. As a result of this, once session data is serialised, it is signed and sent to the user's client under the session cookie.
There is no mention in Pyramid's documentation that sessions are also cached server-side (under this SessionFactory).
This presents a contradiction and has also led to authentication confusion when paired with SessionAuthenticationPolicy. If session data cannot be retrieved from the client's session cookie (as it is one-way hashed), how is it that the following is possible?
Authenticate with the application such that reading Request.authenticated_userid does not return None.
Copy the session cookie to the clipboard.
Logout by accessing a view whereby the headers from forget(request) are returned in the Response.
Replace the session cookie with the copied value.
The user is now logged back in.
I understand that simply deleting the cookie client-side is insufficient to completely invalidate the session (without blacklisting), but this then poses the following questions:
How is it possible to remain secure with browser-scoped sessions unless every session cookie the user has recently been issued is somehow remembered and blacklisted/invalidated?
Is the session cookie actually a key/session ID that's being used to lookup a session in memory? As it's one-way signed, surely this is the only explanation?
Is it possible then to invalidate sessions server-side, a little more robust than just the headers=forget(request) pattern?
Ultimately, I imagine the answer is something along the lines of:
"Maintain server-side sessions using an include such as pyramid_redis_sessions"
Any explanation would be appreciated.
The cookie contains all of the data. The session content itself is stored in the cookie, alongside an hmac signature of that content. This means that a client may view the content if they try hard enough, but they cannot change it as they cannot create trusted signatures without the server-side secret.
How is it possible to remain secure with browser-scoped sessions unless every session cookie the user has recently been issued is somehow remembered and blacklisted/invalidated?
It depends what you're using the session for - you need to take these issues into consideration before putting data into a session object.
Is it possible then to invalidate sessions server-side, a little more robust than just the headers=forget(request) pattern?
Not unless you store some sort of id in the session and then a server-side table of blacklisted ids. If you did this then you could write your own wrapper session-factory that opened the session, checked the id, and returned an empty one if it was blacklisted. Of course then you might just want to use a server-side session library like pyramid_redis_sessions or pyramid_beaker with one of its server-side-storage backends.

Doubts regarding Server side session using caching or cookie based sessions

I am pretty new to web development. I am working with Flask, Sqlalchemy and Postgresql.
As far as I have understood, every new request is like a new thread of the program. New sqlalchemy session is created using which we manage our db operations and return a response. After that new thread is also closed and connections returned to the pool.
I login a user and get all user data in an user orm object. I stored it in flask session variable which uses cookie. Now I also want to save some other user related data for the span of whole user session not a request. I have doubts storing all that data in a cookie for 2 reasons:
1. Unnecessary data travel back and forth.
2. data can be read easily.
Are my doubts valid?
So my other questions are :
Am I right on some level to avoid getting some session wide data in each request without getting into the trap of premature optimization?
or
Should I worry about this later when need arises and right now concentrate only on creating a working app?
Alternative to cookie based session is server side session which can be done by using redis or memcache. Where does Beaker library comes into this? Is it a standalone thing or to be used in conjunction with redis or memcache?
Most browsers support cookies of up to 4096 bytes. (Source)
If you want to save more than this than you should use a server-side session backend like Redis or Memcache. It's very easy to replace the default cookie session interface of Flask with a Redis or Memcache interface. There is a great snippet for redis by Armin. If you prefere memcache than you can replace the redis stuff of the snippet with the same memcache methods. ;)

python reverse proxy spawning via cgi

I need to write a cgi page which will act like a reverse proxy between the user and another page (mbean). The issue is that each mbean uses different port and I do not know ahead of time which port user will want to hit.
Therefore want I need to do is following:
A) Give user a page which will allow him to choose which application he wants to hit
B) spawn a reverse proxy base on information above (which gives me port, server, etc..)
C) the user connects to the remote mbean page via the reverse proxy and therefore never "leaves" the original page.
The reason for C is that user does not have direct access to any of the internal apps only has access to initial port 80.
I looked at twisted and it appears to me like it can do the job. What I don't know is how to spawn twisted process from within cgi so that it can establish the connection and keep further connection within the reverse proxy framework.
BTW I am not married to twisted, if there is another tool that would do the job better, I am all ears. I can't do things like mod_proxy (for instance) since the wide range of ports would make configuration rather silly (at around 1000 different proxy settings).
You don't need to spawn another process, that would complicate things a lot. Here's how I would do it based on something similar in my current project :
Create a WSGI application, which can live behind a web server.
Create a request handler (or "view") that is accessible from any URL mapping as long as the user doesn't have a session ID cookie.
In the request handler, the user can choose the target application and with it, the hostname, port number, etc. This request handler creates a connection to the target application, for example using httplib and assigns a session ID to it. It sets the session ID cookie and redirects the user back to the same page.
Now when your user hits the application, you can use the already open http connection to redirect the query. Note that WSGI supports passing back an open file-like object as response, including those provided by httplib, for increased performance.

Why store sessions on the server instead of inside a cookie?

I have been using Flask for some time now and I am really enjoying the framework. One thing that I fail to understand is that in almost all other places they talk about storing the session on the server and the session id on the client, which would then identify the session. However after using flask, I dont feel the need to do so. Saving the session as a cookie on the client cryptographically serves my purpose and seems quite secure too. The only thing being I am unable to encrypt the session keys for eg:
session['life'] = 'the great one'
would appear as
life='gfhjfkjdfa some encryption kj'
in the cookie saved on the client. But how would that matter as it is still encrypted.
I am sure that people here know things much better than I do, so request someone to please clarify :-)
Even if your data is encrypted, the user could still roll back their cookie to a previous state (unless you start encoding one-time IDs etc)
e.g. cookie says the user has 100 credits, user spends 100 credits, they get a new cookie saying they have 0 credits. They could then restore their previous cookie (with 100 credits).
Depending how you encrypt the cookie, the user may also be able to delete keys, insert bogus data etc too.
If the session data is needed at the server, it makes sense to store it at the server. It keeps down the data bulk sent back and forth from the client. Also, cookies have a limit on the amount of data they can store.
In addition to the points already mentioned above
Users can disable cookies using their browser settings.
A lot of antivirus scanners also scan and flag cookies as a risk because of which which can also result in cookies not being allowed on the users computer.
Cookies can be deleted by the user even in the middle of his session. (In fact, i inadvertently did that the other day when one my PC scans listed the tracking cookies...and i just clicked "Clean" and they were all gone). In case the user happens to delete the cookies, the users state will be lost.
If you use cookies to manage the entire state, you are always dependant on the client environment and its settings. In as such, you will probably atleast need a fall back mechanism in case the cookies are deleted / disabled etc in order for your application to work correctly.
The SecureCookie implementation Flask uses does not encrypt the values. The only thing that is being ensured is that the user cannot modify the cookie without knowing the secret used by the application.

Bind arbitrary Python objects to CherryPy sessions

I'm using CherryPy to make a web-based frontend for SymPy that uses an asynchronous process library on the server side to allow for processing multiple requests at once without waiting for each one to complete. So as to allow for the frontend to function as expected, I am using one process for the entirety of each session. The client-side Javascript sends the session-id from the cookie to the server when the user submits a request, and the server-side currently uses a pair of lists, storing instances of a controller class in one and the corresponding session-id's in another, creating a new interpreter proxy and sending the input if a non-existant session-id is submitted. The only problem with this is that the proxy classes are not deleted upon the expiration of their corresponding sessions. Also, I can't see anything to retrieve the session-id for which the current request is being served.
My questions about all this are: is there any way to "connect" an arbitrary object to a CherryPy session so that it gets deleted upon session expiration, is there something I am overlooking here that would greatly simplify things, and does CherryPy's multi-threading negate the problem of synchronous reading of the stdout filehandle from the child process?
You can create your own session type, derived from CherryPy's base session. Use its clean_up method to do your cleanup.
Look at cherrypy/lib/sessions.py for details and sample session implementations.

Categories