4

以下のスクリプトを検討してください。2 つのサブプロセスが起動され、それぞれが CherryPy アプリです (両方を終了するには、Ctrl+C を押すか、システムにある KeyboardInterrupt コンボを押します)。CP 3.0 で実行する場合 (「StartServer」の 3.0/3.1 固有の行を変更するように注意してください)、次にアクセスします。

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)
4

2 に答える 2

3

セッション識別子が保存されているCookieは、host+portではなくhostにバインドされています。最初のサイトにアクセスすると、3.1(3.0ではない)で新しいセッションIDを取得し、セッションデータを入力して表示できます。その後、このセッションIDで他のポートに移動しますが、現在は無効です(これは、デバッグモードのログで確認できると思います)。したがって、サーバーは新しいセッションIDを送信します。ここで最初のサーバーに戻りますが、識別子が無効であるため、新しい識別子を取得します。確かに、この新しい識別子のセッションにはデータがありません。

更新:RFC 2109、セクション4.3.1 Set-Cookieの解釈:

ユーザーエージェントは、各オリジンサーバーからSet-Cookie応答ヘッダーを介して到着する状態情報を個別に追跡します(名前またはIPアドレスとポートで区別されます)。

しかし、標準の解釈はそれほど明白ではありません。これは、 Firefoxトラッカーの関連チケットからの引用です。

Cookieには、2109(set-cookieの場合)と2965(set-cookie2の場合)の2つのRFCがあります。

セクション4.3.1のRFC2109では、Set-Cookieの解釈に次のように記載されています。
「ドメインのデフォルトはrequest-hostです。」そして、セクション2 TERMINOLOGYには、「request-hostとrequest-URIという用語は、クライアントがサーバーにそれぞれホスト(ポートではない)として送信する値を指します。 HTTPリクエスト行のabsoluteURI(http_URL)のabs_path部分。request-hostはFQHNである必要があることに注意してください。」RFC 2965のセクション3.3.1では、Set-Cookie2の解釈に、「ドメインのデフォルトは有効なリクエストホストに」と記載されています。また、「ポートデフォルトの動作では、Cookieは任意のリクエストポートに返される可能性があります。」と記載されています。 1 TERMINOLOGY「request-hostおよびrequest-URIという用語は、クライアントがサーバーに送信する値をそれぞれ参照します。HTTPリクエストラインのabsoluteURI(http_URL)のホスト(ポートではない)とabs_pathの部分。"(RFC 2109と同じように)

私の解釈では、set-cookie2ヘッダーでポート番号が明示的に定義されていない限り、Cookieドメインの記録にポート番号を使用しないでください。

于 2010-04-12T10:53:49.103 に答える
1

TL;DR : CherryPy 構成パラメーターtools.sessions.nameを各アプリケーションに固有のものに変更します。

長い答え:

これは非常に古い質問であることは承知していますが、非常に簡単な答えがあると思います。将来の検索者のために以下に書きます。

CherryPy は Cookie を使用してセッションを見つけます。デフォルトでは、これは「session_id」と呼ばれ、値としてランダムな 16 進文字列を持ちます。CherryPy に認識できない session_id が与えられると、新しい session_id が生成されます。これは、セッションの固定化を防ぐための措置です。

同じドメインに 2 つのアプリケーションがある場合。どちらも同じ Cookie 名 (つまり、「session_id」) を使用しますが、どちらも他方の session_id を認識しないため、新しいもので上書きします。したがって、あるアプリケーションから別のアプリケーションに移動すると、セッションが無効になります。

tools.sessions.name解決策は簡単です。CherryPy 構成では、「myapp_session_id」や「myotherapp_session_id」など、「session_id」以外に設定することで、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 でこれをテストしたことはありませんが、ソース コードを見ると、10 年以上前から可能だったようです。

これを書いて以来、私はこれに関するCherryPyのドキュメントに更新を寄稿しました

于 2017-07-12T19:18:51.683 に答える