Сеансы CherryPy для одного домена, другого порта - PullRequest
4 голосов
/ 08 апреля 2010

Рассмотрим скрипт ниже. Он запустит два подпроцесса, каждый из которых представляет собой приложение CherryPy (нажмите Ctrl + C или любую комбинацию KeyboardInterrupt в вашей системе, чтобы завершить их оба). Если вы запускаете его с CP 3.0 (стараясь изменить определенные строки 3.0 / 3.1 в «StartServer»), тогда посетите:

http://localhost:15002/

... вы видите пустой диктант. Тогда посетите:

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

http://localhost:15002/

... и вы видите недавно населенный диктат. Тогда посетите:

http://localhost:15012/

... и вернитесь к

http://localhost:15002/

... и ничего не изменилось.

Если вы попробуете то же самое с CP 3.1 (помните строки в «StartServer»!), Когда вы дойдете до последнего шага, dict теперь пуст. Это происходит в Windows и Debian, Python 2.5 и 2.6.

Вы можете попробовать всевозможные вещи: перейти на файловое хранилище, разделить пути хранения ... единственное отличие, которое он имеет, состоит в том, что сессии могут быть объединены, а не удалены. Я прочитал еще один пост об этом также, и есть предложение поместить ключи конфигурации инструментов сеанса в конфигурацию приложения, а не в глобальную конфигурацию, но я не думаю, что это имеет отношение к этому использованию где приложения работают независимо друг от друга.

Что мне делать, чтобы независимые приложения CherryPy НЕ мешали друг другу?

Примечание: я изначально спрашивал об этом в CherryPy списке рассылки , но еще не получил ответа, поэтому я пытаюсь здесь. Я надеюсь, что все в порядке.

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)

Ответы [ 2 ]

3 голосов
/ 12 апреля 2010

Файл cookie, в котором хранится идентификатор сеанса, привязан к хосту, а не к хосту + порту. Когда вы посещаете первый сайт, вы получаете новый идентификатор сеанса в 3.1 (но не в 3.0) , затем вы заполняете данные сеанса и видите их. После этого вы переходите на другой порт с этим идентификатором сеанса, но теперь он недействителен (я полагаю, вы можете увидеть это в журнале в режиме отладки). Таким образом, сервер отправляет вам новый идентификатор сессии. Теперь вы возвращаетесь на первый сервер, и ваш идентификатор снова становится недействительным, поэтому вы получаете новый. Конечно, в этом сеансе нет данных для этого нового идентификатора.

Обновление : RFC 2109, раздел 4.3.1 Интерпретация Cookie-набора говорит:

Пользовательский агент ведет отдельный учет информация о состоянии, которая поступает через Заголовки ответа Set-Cookie от каждого сервер происхождения (в отличие от имя или IP-адрес и порт).

Но интерпретация стандарта не так очевидна. Вот цитата из связанного билета в трекере Firefox:

Есть два RFC для печенья, 2109 (Для set-cookie) и 2965 (для установленный Cookie2)

В RFC 2109 в разделе 4.3.1. Интерпретация Set-Cookie в нем
"Домен по умолчанию для запроса хоста. И в разделе 2 ТЕРМИНОЛОГИЯ это говорится "Условия запроса хоста и Request-URI ссылаются на значения клиент отправит на сервер как, соответственно хост (но не порт) и abs_path части absoluteURI (http_URL) HTTP Строка запроса. Обратите внимание, что запрос-хост должен быть FQHN. "В RFC 2965 в разделе 3.3.1 Интерпретация Set-Cookie2 это заявляет "Домен По умолчанию эффективный запрос-хост. "это также заявляет" Порт По умолчанию поведение таково, что печенье МОЖЕТ быть вернулся на любой запрос-порт. И в разделе 1 ТЕРМИНОЛОГИЯ это заявляет "Условия request-host и request-URI ссылаются на ценности клиента отправил бы на сервер как, соответственно, хост (но не порт) а также части abs_path absoluteURI (http_URL) HTTP Строка запроса. "(Так же, как RFC 2109)

Моя интерпретация этого такова, что номера портов не должны использоваться для запись файлов cookie, если только заголовок set-cookie2 явно определяет номер порта.

1 голос
/ 12 июля 2017

TL; DR : измените параметр конфигурации CherryPy tools.sessions.name на что-то уникальное для каждого приложения.

Длинный ответ :

Я знаю, что это очень старый вопрос, но я думаю, что есть очень простой ответ. Пишем ниже для будущих искателей.

CherryPy использует куки для поиска сессий. По умолчанию это называется "session_id" и имеет случайную шестнадцатеричную строку в качестве значения. Если CherryPy присваивается идентификатор сеанса, который он не распознает, он генерирует новый идентификатор сеанса. Это мера для предотвращения фиксации сеанса.

Если у вас есть два приложения в одном домене. Они оба используют одно и то же имя файла cookie (т. Е. "Session_id"), но ни один не распознает session_id другого, и поэтому они перезаписывают его новым. Поэтому переход из одного приложения в другое делает сеанс недействительным.

Решение простое: в конфигурации CherryPy вы можете переопределить имя session_id, задав tools.sessions.name значение, отличное от «session_id», например «myapp_session_id» и «myotherapp_session_id».

Вы должны убедиться, что хранилище сеанса отдельно, как вы правильно определили.

Из приведенного выше примера вы бы сделали что-то вроде этого:

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
    }
}

Примечание. В моих собственных приложениях, использующих CherryPy 10.0.0, я использовал этот параметр конфигурации на уровне приложений и на уровне пути. Я не проверял это на старых версиях CherryPy, но, глядя на исходный код, похоже, что это возможно уже более десяти лет.

С тех пор, как я написал это, я добавил обновление документации CherryPy об этом, включенное здесь: http://docs.cherrypy.org/en/latest/pkg/cherrypy.lib.html#session-fixation-protection

...