CherryPy classes for one domain, different ports

Consider the script below. It will launch two subprocesses, each of which is a CherryPy application (press Ctrl + C or something like KeyboardInterrupt combo on your system to finish both of them). If you run it using CP 3.0 (taking care of changing individual 3.0 / 3.1 lines to "StartServer"), go to the page

http: // localhost: 15002 /

... you see an empty dict. Then visit:

http: // localhost: 15002 / set? val = 10

http: // localhost: 15002 /

... and you see the recently populated dict. Then visit:

http: // localhost: 15012 /

... and go back to

http: // localhost: 15002 /

... and nothing has changed.

If you try to do the same with CP 3.1 (remember the lines in "StartServer"!), When you get to the last step, the dict is now empty. This happens on Windows and Debian, Python 2.5 and 2.6.

You can try all sorts of things: go to the file vault, sharing storage paths ... The only difference he makes is that the sessions can be merged, not erased. I read another post about this, and there is a proposal to put the session tool configuration keys in the application configuration, not the global configuration, but I do not think that this applies to this use when the applications work independently.

What should I do to make CherryPy independent applications NOT interfere with each other?

Note. I originally asked about this on the CherryPy mailing list , but haven’t received an answer yet, so I am trying here. I hope everything is in order.

import os, os.path, socket, sys import subprocess import cgi import cherrypy HTTP_PORT = 15002 HTTP_HOST = "127.0.0.1" site1conf = { 'global' : { 'server.socket_host' : HTTP_HOST, 'server.socket_port' : HTTP_PORT, 'tools.sessions.on' : True, # 'tools.sessions.storage_type': 'file', # 'tools.sessions.storage_path': '1', # 'tools.sessions.storage_path': '.', 'tools.sessions.timeout' : 1440}} site2conf = { 'global' : { 'server.socket_host' : HTTP_HOST, 'server.socket_port' : HTTP_PORT + 10, 'tools.sessions.on' : True, # 'tools.sessions.storage_type': 'file', # 'tools.sessions.storage_path': '2', # 'tools.sessions.storage_path': '.', 'tools.sessions.timeout' : 1440}} class Home(object) : def __init__(self, key): self.key = key @cherrypy.expose def index(self): return """\ <html> <body>Session: <br>%s </body> </html> """ % cgi.escape(str(dict(cherrypy.session))) @cherrypy.expose def set(self, val): cherrypy.session[self.key.upper()] = val return """\ <html> <body>Set %s to %s</body> </html>""" % (cgi.escape(self.key), cgi.escape(val)) def StartServer(conf, key): cherrypy.config.update(conf) print 'Starting server (%s)' % key cherrypy.tree.mount(Home(key), '/', {}) # Start the web server. #### 3.0 # cherrypy.server.quickstart() # cherrypy.engine.start() #### #### 3.1 cherrypy.engine.start() cherrypy.engine.block() #### def Main(): # Start first webserver proc1 = subprocess.Popen( [sys.executable, os.path.abspath(__file__), "1"]) proc2 = subprocess.Popen( [sys.executable, os.path.abspath(__file__), "2"]) proc1.wait() proc2.wait() if __name__ == "__main__": print sys.argv if len(sys.argv) == 1: # Master process Main() elif(int(sys.argv[1]) == 1): StartServer(site1conf, 'magic') elif(int(sys.argv[1]) == 2): StartServer(site2conf, 'science') else: sys.exit(1) 
+4
source share
2 answers

The cookie where the session identifier is stored is bound to the host, not the host + port. When you visit the first site, you get a new session identifier in 3.1 (but not 3.0) , then you fill in the session data and you can see it. After that, you switch to another port with this session ID, but now it is not valid (I believe that you can see this in debug mode in the log). Thus, the server sends you a new session identifier. Now you are returned to the first server and again your identifier is invalid so you get a new one. Of course, there is no data in the session for this new identifier.

Update : RFC 2109, Section 4.3.1 Interpretation of Set-Cookie says:

The user agent saves a separate track of status information that comes through the Set-Cookie header headers from each source (as opposed to the name or IP address and port).

But the interpretation of the standard is not so obvious. Here is a quote from the linked in firefox tracker:

There are two RFCs for cookies, 2109 (for set-cookies) and 2965 (for set-cookies2)

In RFC 2109, in Section 4.3.1, Interpretation of a Set-Cookie contains the state "Default domain for the request node." And in section 2 “TERMINOLOGY” of the status “The terms request-host and request-URI refer to the values ​​the client sends to the server, as, respectively, the host (but not the port) and abs_path absoluteURI (http_URL) HTTP request. Note that request- host must be FQHN ". In RFC 2965, in section 3.3.1, Interpretation of Set-Cookie2 contains "Domain By default, the host request is valid." it also says Port. The default behavior is that a cookie MAY be returned to any port request. "And in section 1, TERMINOLOGY says:" The terms request-host and request-URI refer to client values ​​and will send the server, respectively, the host (but not the port) as well as the abs_path of the absoluteURI part (http_URL) of the HTTP request. "(Same as RFC 2109)

My interpretation is that port numbers should not be used to record cookie domains if the set-cookie2 header explicitly defines the port number.

+3
source

TL DR : change the configuration parameter of CherryPy tools.sessions.name to something unique for each application.

Long answer :

I know this is a very old question, but I think there is a very simple answer. Writing below for future search engines.

CherryPy uses cookies to search for sessions. By default, this is called session_id and has a random hexadecimal string as the value. If CherryPy receives a session_id that it does not recognize, it will generate a new session_id. This is a measure to prevent session fixation.

If you have two applications in the same domain. They both use the same cookie name (ie, "Session_id"), but do not recognize the session_id of the other and therefore overwrite it with a new one. Therefore, switching from one application to another cancels the session.

The solution is simple: in the CherryPy configuration, you can redefine the session_id name by setting tools.sessions.name to something other than "session_id", for example, "myapp_session_id" and "myotherapp_session_id".

You need to make sure that the session store is separate, as you correctly defined.

In the above example, you would do something like this:

 site1conf = { 'global': { 'server.socket_host': HTTP_HOST, 'server.socket_port': HTTP_PORT, 'tools.sessions.on': True, 'tools.sessions.storage_type': 'file', 'tools.sessions.storage_path': '/tmp/site1_sessions/', 'tools.sessions.name': 'site1_session_id', 'tools.sessions.timeout': 1440 } } site2conf = { 'global': { 'server.socket_host': HTTP_HOST, 'server.socket_port': HTTP_PORT + 10, 'tools.sessions.on': True, 'tools.sessions.storage_type': 'file', 'tools.sessions.storage_path': '/tmp/site2_sessions/', 'tools.sessions.name': 'site2_session_id', 'tools.sessions.timeout': 1440 } } 

Note. In my own applications using CherryPy 10.0.0, I used this configuration parameter at the application level and at the path level. I have not tested this with older versions of CherryPy, but looking at the source code, it seems like this has been possible for more than a decade.

Since writing this document, I have implemented an update to CherryPy's documentation about this, included here: http://docs.cherrypy.org/en/latest/pkg/cherrypy.lib.html#session-fixation-protection

+1
source

Source: https://habr.com/ru/post/1306319/


All Articles