セッション

セッション

Note

セッションコードは大幅な書き直しが必要です。それはキャッシングにお いてより一般的な使用パターン (たまにしかないアップデート/頻繁な読み 取り) に最適化された Beaker の Caching コンテナ API を使用していま す。キャッシュとは異なり、セッションは一度だけロードされ、そして一 度だけ保存されます。そして同じセッションに対して複数の書き込みが同 時に起こることはめったにありません。そのため、現在のキャッシュイン タフェースが行う過剰な、しかし必要なロックは、セッションに関しては 単なる性能の浪費です。

セッションオブジェクト

SessionObject

このセッションプロキシ/遅延作成オブジェクトは、本物のセッションオブジェ クトへのアクセスを処理します。セッションがそれまでに使用されたことがな ければ、セッションオブジェクトは自動的に作成されてセットアップされます。 本物のセッションオブジェクトへのアクセスを扱うのにこのようなやり方でプ ロキシを使用するのは、リクエストの間にセッションが実際に使用されない場 合に、セッションを作成して永続的なストレージからロードするのを避けるた めです。

CookieSession

純粋なクッキーベースのセッション。クッキーベースのセッションを使用する 際に認識されるオプションは、一般的なセッションよりわずかに制限されてい ます。

  • key

    クッキーにセットされる名前。

  • timeout

    セッションデータがどの程度の期間有効とみなすか。これはクッキーが存 在しているかどうかにかかわらず、セッションデータがまだ有効であるか どうかを決定するために使用されます。

  • encrypt_key

    セッション暗号化のために使用するキー。指定しなければセッションは暗 号化されません。

  • validate_key

    暗号化されたセッションに署名するために使用されるキー。

  • cookie_domain

    クッキーに使用するドメイン。

  • secure

    クッキーが SSL を通じてのみ送られるかどうか。

Beaker

beaker.session.key = wiki
beaker.session.secret = ${app_instance_secret}

Pylons にはキャッシュミドルウェアが有効な状態で付属しています。それはセッ ションの取り扱いを提供するのと同じパッケージである Beaker の一部です。 Beaker はいくつかの異なる種 類のキャッシュバックエンドをサポートします: メモリ, ファイルシステム, memcached, そしてデータベースです。サポートされるデータベースパッケージ は、 SQLite, SQLAlchemy, および Google BigTable です。

Beaker のキャッシュとセッションオプションは辞書で構成されます。

Note

Paste パッケージと共に使用する場合、 Beaker が自身のオプションと他 のアプリケーションの設定オプションを区別できるように、すべての Beaker オプションは beaker. プリフィックスをつけるべきです。

一般的な設定オプション

設定オプションは session. または cache. プリフィックスをつける べきです。

data_dir

Accepts: string Default: None

キャッシュデータが保存されるデータディレクトリ。この引数が存在していな いなら、通常の data_dir パラメータに ”./sessions” を追加したものが 使用されます。

type

Accepts: string Default: dbm

セッションに使用されるストレージのタイプ。現在のタイプは “dbm”, “file”, “memcached”, “database”, および “memory” です。ストレージはキャッ シュシステムも使用する Container API を使用します。

dbm ファイルを使用する場合、各ユーザのセッションは beaker.container.DBMNamespaceManager クラスを通してそれぞれ別 の dbm ファイルに保存されます。

‘database’ または ‘memcached’ を使用する場合、以下の対応するセクション で文書化されるように、追加の設定オプションが必要です。

セッションオンリーには、 “cookie” タイプの追加選択があります。 それはセッションに “secret” オプションが設定されることを必要とします。

データベース設定

タイプが ‘database’ にセットされているとき、以下の追加オプションを使用 できます。

url (required)

Accepts: string (SQLAlchemy db uri と同じ書式) Default: None

SQLAlchemy がデータベースに対して使用する書式と同様のデータベース URI 。 データベースのための適切なデータベースパッケージもインストールしなけれ ばなりません。

table_name

Accepts: string Default: beaker_cache

Beaker のストレージに使用するテーブル名。

optimistic

Accepts: boolean Default: False

楽観的なセッションロックを使用します。この場合、キャッシュ値をアップデー トするときに、バージョン番号を比較するために select が行われることに注 意してください。

sa_opts (Only for SQLAlchemy 0.3)

Accepts: dict Default: None

SQLAlchemy のエンジンに直接渡される値の辞書。これは SQLAlchemy 0.3 に対 してのみ適切であることに注意してください。

sa.*

Accepts: 有効な SQLAlchemy 0.4 データベースオプション Default: None

SQLAlchemy 0.4 以上を使用するとき、プリフィックスに sa. を持つすべ てのオプションが SQLAlchemyデータベースエンジンに渡されます。 一般的な パラメータは pool_size, pool_recycle などです。

memcached オプション

url (required)

Accepts: string Default: None

url は memcached のための 単一の IP アドレスか、セミコロンで区切られた IP アドレスのリストです。

Beaker は memcached と通信するのに py-memcached または cmemcache のどち らかを使用できますが、 cmemcache は memcached に接続できなくなったとき に Python を segfault させることがあることに注意してください。

セッションオプション

id

Accepts: string Default: None

このセッションのためのセッション id。 クッキーとともにセッションを使用 する場合、セッションはリクエストから自動的に値を作成、保存、取得するの で、このパラメータは必要ありません。セッションに URL ベースの方法を使用 する場合、セッションが最初に作成されるときに id は id データメンバーか ら取得され、次に新しい URL を出力する際に使用されます。

key

Accepts: string Default: beaker_session_id

セッションを特定するためにクッキーのキーとして使用されるキー。これを変 えることで、いくつかの異なったアプリケーションが同じホスト名の下で異な るセッションを持つことができます。

secret

Accepts: string Default: None

暗号化セッション id を有効にする秘密鍵。 None でないときに、セッション id はこの値に対して作成された MD5 署名で生成されます。

“cookie” セッションタイプで使用されると、 secret はクッキーの内容を暗号 化するために使用されます。十分にセキュアな、少なくとも 54 文字以上のラ ンダムに生成された文字列にすべきです。

timeout

Accepts: integer Default: None

セッションがタイムアウトするまでの秒数。セッションが timeout 秒以上ロー ドされなかった場合、タイムアウトが起こります。

セッションオプション (クッキーベースセッションを使う場合)

encrypt_key

Accepts: string Default: None

セッション暗号化に使用するキー。指定しなければセッションは暗号化されま せん。これは pycryptopp や Python 2.5 の hashlib.sha256 のような強いハッ シュスキームが利用可能である場合にだけ働きます。

validate_key

Accepts: string Default: None

暗号化されたセッションに署名するために使用されるキー。これは secret オ プションの代わりに使用されます。

カスタムミドルウェア

カスタムミドルウェアをどのレイヤーに置くかを決める際には注意が必要です。 多くの場合、ミドルウェアは Pylons WSGI アプリケーションインスタンスと Routes ミドルウェアの間に置かれるべきです。しかし、ミドルウェアがセッショ ンオブジェクトやルーティングが扱われるより 前で 実行する必要があるな ら:

# Routing/Session/Cache Middleware
app = RoutesMiddleware(app, config['routes.map'])
app = SessionMiddleware(app, config)

# MyMiddleware can only see the cache object, nothing *above* here
app = MyMiddleware(app)

app = CacheMiddleware(app, config)

Session, Routes, Cache ミドルウェアなどのいくつかの Pylons ミドルウェア層は、単に environ 辞書にオブジェクトを加えるか、またはレ スポンスに HTTP ヘッダを加えるだけです (例えば Session ミドルウェアはセッ ションクッキーヘッダーを加えます)。一方、 Status Code Redirect や Error Handler は、リクエスト全体を完全に横取りして、そのレスポンス を変えるかもしれません。

db に保持されたセッションの bulk 削除

Session のための db スキーマは、各セッションについて「最後にアクセスさ れた時間」を格納します。これによって、簡単な SQL コマンドを使用すること で期限切れのセッションの bulk 削除が可能になります。 SQL コマンドは毎日 実行され、「最後にアクセスされた」タイムスタンプが 2 日より前 (あるいは その他の任意の条件で) 期限切れのセッションをクリアします。

国際化に Session を使用する

コントローラで使用される言語を動的に (on the fly) 設定する方法。

例えばこれを使えば、ユーザがアプリケーションをどの言語で動かしたいか 設定できるようになります。セッションオブジェクトに値を保存してください:

session['lang'] = 'en'
session.save()

そうすると、各コントローラが呼び出された時にコントローラの __before__() メソッドでセッションから言語を読み込んで設定することに よって、継続して設定された言語でページが表示されるようになります。

def __before__(self):
    if 'lang' in session:
        set_lang(session['lang'])

Secure Form で Session を使用する

権限トークンはクライアントのセッションに格納されます。そして、ウェブア プリは、送信されたリクエストの権限トークンをクライアントのセッションに 保存された値に対して検証することができます。

これはリクエストが originating ページから来たことを保証します。 クロス サイト・リクエスト・フォージュリ に関して詳しい情報は wikipedia のエ ントリーを見てください。

Pylons はコントローラに代わってこの検証を行う authenticate_form デ コレータを提供しています。

これらの helpers は Pylons の session オブジェクトに依存しています。 それらの大部分は、 API 呼び出しを変えることによって容易に別のフレームワー クに移植できるでしょう。

クッキーを使用しないセッションの hack

(From a paste #441 baked by Ben Bangert)

dev.ini ファイルでセッションにクッキーを使用しないように設定してください。

beaker.session.use_cookies = False

そしてコントローラアクションの中で mode d’emploi (使用法、取扱説明書) としてこのようにします:

from beaker.session import Session as BeakerSession

# Get the actual session object through the global proxy
real_session = session._get_current_obj()

# Duplicate the session init options to avoid screwing up other sessions in
# other threads
params = real_session.__dict__['_params']

# Now set the id param used to make a session to our session maker,
# if id is None, a new id will be made automatically
params['id'] = find_id_func()
real_session.__dict__['_sess'] = BeakerSession({}, **params)

# Now we can use the session as usual
session['fred'] = 42
session.save()

# At the end, we need to see if the session was used and handle its id
if session.is_new:
    # do something with session.id to make sure its around next time
    pass

(Beaker) ミドルウェアを composite app と共に使用する

呼び出された WSGI アプリケーションが共通のセッション管理ユーティリティ を共有するのを許可する方法。

(From a paste #616 baked by Mark Luffel)

# Here's an example of configuring multiple apps to use a common
# middleware filter
# The [app:home] section is a standard pylons app
# The ``/servicebroker`` and ``/proxy`` apps both want to be able
# to use the same session management

[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 5000

[filter-app:main]
use = egg:Beaker#beaker_session
next = sessioned
beaker.session.key = my_project_key
beaker.session.secret = i_wear_two_layers_of_socks

[composite:sessioned]
use = egg:Paste#urlmap
/ = home
/servicebroker = servicebroker
/proxy = cross_domain_proxy

[app:servicebroker]
use = egg:Appcelerator#service_broker

[app:cross_domain_proxy]
use = egg:Appcelerator#cross_domain_proxy

[app:home]
use = egg:my_project
full_stack = true
cache_dir = %(here)s/data

SA マップされたオブジェクトを Beaker セッションに保存する

pylons-discuss Google グループの議論から:

> I wouldn't expect a SA object to be serializable.  It just doesn't
> make sense to me.  I don't even want to think about complications with
> the database and ACID, nor do I want to consider the scalability
> concerns (the SA object should be tied to a particular SA session,
> right?).

(直訳)
私は SA オブジェクトがシリアライズ可能とは思っていません。それは単
に私には理解できません。私はデータベースと ACID の複雑さについて考
えたくありませんし、スケーラビリティについても関心を持ちたくありま
せん。 (SA オブジェクトは特定の SA セッションに結びつけられるべきで
すよね?)

SA オブジェクトはシリアライズ可能です。 (assign_mapper() を使って いない場合。それは __getstate__() を定義しないと物事を複雑にします)

上記のエラーは entity が元のセッションから detach されていないことが原 因です。シリアライズする際は、オブジェクトを手動で適切なセッションの間 を往復させなければなりません。

シリアライズしたオブジェクトを SA Session に戻すには、以下の 3 通りの方 法があります:

  1. __getstate__() を持っているマップされたクラスは desired プロパ ティだけをコピーして、SA セッションポインタをコピーしません。

    beaker.put(key, obj)
    ...
    obj = beaker.get(key)
    Session.add(obj)
    
  1. 通常の古いマップされたクラス。 expunge() ステップを加えてください。

    Session.expunge(obj)
    beaker.put(key, obj)
    ...
    obj = beaker.get(key)
    Session.add(obj)
    
  1. オリジナルのオブジェクトについては __getstate__() や expunge() について気にする必要はありません。 merge() を 使用してください。これは上で示した expunge() メソッドよりクリー ンな方法ですが、通常はデータベースからオブジェクトをロードすることを 強制するので、必ずしも「効率的」ではないかもしれません。またそれは与 えられたオブジェクトの状態を対象のオブジェクトにコピーしますが、これ は間違いの元かもしれません。

    beaker.put(key, obj)
    ...
    obj = beaker.get(key)
    obj = Session.merge(obj)