(機械翻訳) セキュリティ¶
:app: Pyramid`はオプションで宣言的なセキュリティシステムを提供します。セキュリティで:app: `Pyramid`は認証と認可に分かれています。 2つのシステムはterm: `principal`識別子で通信します。認証は単に:term: `request`で提供された資格証明が1つ以上の:term: principal`識別子に解決されるメカニズムです。これらの識別子は、要求時に有効なユーザーとグループを表します。承認は:term: principal`識別子、要求された:term: permission`、およびa:term: `context`に基づいてアクセスを決定します。
:app: Pyramid`認可システムは:term:`認可ポリシー `に基づいてa:term: view`が呼び出されるのを防ぐことができます。ビューが呼び出される前に、認証システムは:term: context`リソースとともに、:term: request`の資格情報を使用して、アクセスが許可されるかどうかを判断することができます。どのように高いレベルで動作するかは次のとおりです。
- ユーザーは以前にアプリケーションを訪れていてもいなくてもかまいませんし、:term: `userid`を含む認証資格情報を提供しているかもしれません。もしそうなら、アプリケーションはfunc: `pyramid.security.remember`を呼び出してこれらを覚えているかもしれません。
- A:term: `request`は、ユーザがアプリケーションを訪れたときに生成されます。
- この要求に基づいて、a:term: context`リソースは:term: resource location`によって配置されます。コンテキストは、アプリケーションがterm: traversal`または:term: URL dispatch`を使用するかどうかによって異なって位置付けられますが、どちらの場合でもコンテキストは最終的に見つかります。詳細は、:ref: `urldispatch_chapter`の章を参照してください。
- A:term: view callable`は:term: view lookup`によってコンテキストのほかにリクエストの他の属性を使用しています。
- :term: `認証ポリシー`が有効な場合、要求に渡されます。いくつかの:term: `principal`識別子を返します。これを行うには、ポリシーは、リクエストに存在するauthenticated:term: `userid`を判断する必要があります。
- :term: 認可ポリシー`が有効であり、見つかったビューcallableに関連付けられた:term: `view configuration`に:term: permission`が関連付けられている場合、認可ポリシーは次のように渡されます:term: context、認証ポリシーによって返されるterm:` principal`識別子、ビューに関連する:term: `permission`です。アクセスを許可または拒否します。
- 権限ポリシーがアクセスを許可する場合、呼び出し可能なビューが呼び出されます。
- 認可ポリシーがアクセスを拒否した場合、呼び出し可能なビューは呼び出されません。代わりに:term: `禁止されたビュー 'が呼び出されます。
承認は、アプリケーションを変更して:term: `認証ポリシー`と:term: `認証ポリシー`を含むようにすることで可能になります。 :app: `Pyramid`には、これらのポリシーのさまざまな実装が付属しています。最大限の柔軟性を提供するために、:app: `Pyramid`ではカスタム認証ポリシーと認証ポリシーを作成することもできます。
承認ポリシーの有効化¶
:app: `Pyramid`は、デフォルトでは、どの認可ポリシーも有効にしていません。すべてのビューには、完全に匿名のユーザーがアクセスできます。セキュリティ設定に基づいてビューを実行から保護するには、認可ポリシーを有効にする必要があります。
権限付きポリシーを必然的に有効にする¶
権限ポリシーを有効にするには、:class: 〜pyramid.config.Configurator`の:meth:〜pyramid.config.Configurator.set_authorization_policy`メソッドを使用します。
権限ポリシーを有効にするには、:term: `認証ポリシー 'も有効にする必要があります。これは、認証は一般に認証に依存するためです。アプリケーション設定中に:meth: `〜pyramid.config.Configurator.set_authentication_policy`メソッドを使用して、認証ポリシーを指定します。
例えば:
1 2 3 4 5 6 7 8 | from pyramid.config import Configurator
from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
authn_policy = AuthTktAuthenticationPolicy('seekrit', hashalg='sha512')
authz_policy = ACLAuthorizationPolicy()
config = Configurator()
config.set_authentication_policy(authn_policy)
config.set_authorization_policy(authz_policy)
|
注釈
`` authentication_policy``と `` authorization_policy``引数は上記のそれぞれのメソッドに渡すこともできます:term:Pythonモジュールスコープで定義された適切な実装グローバルへの点線の名前パスを表す `dotted Python name`値。
上記の設定では、要求の環境で渡された"auth ticket "クッキーの値をsingle:term: userid`への参照を含むポリシーと比較し、そのuseridの:term: principals <principal> ':term: view`を呼び出そうとしたときに、リソースツリーに見つかったany:term: ACL`に存在するプリンシパルに対して。
さまざまな認証ポリシーと認証ポリシーを混在させることは可能ですが、Pyramidアプリケーションを認証ポリシーを使用して設定することはできますが、許可ポリシーは設定しないでください。これを行うと、アプリケーションの起動時にエラーが発生します。
参考
認証と認証ポリシーの代替実装については:mod: pyramid.authorization`と:mod: pyramid.authentication`モジュールも参照してください。
アクセス権によるビューの保護¶
特定のタイプのリソースが:term: context`になったときに、ユーザのセキュリティ設定に基づいて呼び出しから view callable`を保護するには、:term: permission`を:term: view configuration `。パーミッションは通常文字列であり、必要なコンポジションはありません。あなたが好きなようにパーミッションを指定することができます。
たとえば、次のビュー宣言は、コンテキストリソースが:meth: pyramid.config.Configuratorを使用して add``パーミッションを持つ Blog``型である場合、 add_entry.html``という名前のビューを保護します。 add_view API:
1 2 3 4 5 6 | # config is an instance of pyramid.config.Configurator
config.add_view('mypackage.views.blog_entry_add_view',
name='add_entry.html',
context='mypackage.resources.Blog',
permission='add')
|
`` add``許可名を含む等価なビューの登録は、 `` @ view_config``デコレータを使って行うことができます:
1 2 3 4 5 6 7 | from pyramid.view import view_config
from resources import Blog
@view_config(context=Blog, name='add_entry.html', permission='add')
def blog_entry_add_view(request):
""" Add blog entry code goes here """
pass
|
これらの様々なビュー構成ステートメントの結果、通常のアプリケーション操作中にビュー呼び出し可能なものが見つかったときに認証ポリシーが設定されている場合、要求側ユーザーは:term: に対して add``アクセス権を持っている必要があります` blog_entry_add_view``ビューを呼び出せるようにするために `` context``リソースを使います。そうでない場合、:term: `禁止されたビュー 'が呼び出されます。
既定のアクセス許可の設定¶
ビュー構成に権限が与えられていない場合、登録ビューは常に完全に匿名ユーザーによって実行可能になります。有効な権限ポリシーはすべて無視されます。
"デフォルトでセキュリティで保護されている"というアプリケーションを簡単に設定できるようにするため、:app: Pyramid`では*デフォルトの権限を設定することができます。指定されていれば、デフォルトの許可は、それ以外の場合は ` permission``引数に名前を付けないすべてのビュー登録に対する許可文字列として使用されます。
:meth: `pyramid.config.Configurator.set_default_permission`メソッドは、アプリケーションのデフォルトパーミッションの設定をサポートしています。
既定のアクセス許可が登録されている場合:
- ビュー構成が明示的に `` permission``という名前を付けると、そのビューの登録ではデフォルトの権限は無視され、view-configuration-namedの権限が使用されます。
- ビューの設定でpermission:data: `pyramid.security.NO_PERMISSION_REQUIRED`という名前が付けられた場合、デフォルトの権限は無視され、ビューは権限なしで*登録されます(資格に関係なくすべての発信者が利用できるようになります)。
リソースオブジェクトへのACLの割り当て¶
デフォルト:app: Pyramid:term:認可ポリシー 'が、ユーザーがリソースに関して特定の許可を持っているかどうかを判断するとき、リソースに関連付けられた:term: `ACL`を検査します。 ACLは、リソースオブジェクトに ` __acl__``属性を追加することによってリソースに関連付けられます。この属性は、インスタンスレベルのセキュリティが必要な場合はリソース*インスタンス*で定義でき、タイプレベルのセキュリティが必要な場合はリソース*クラス*で定義できます。
たとえば、ブログのリソースにクラスを介してACLを添付することができます。
1 2 3 4 5 6 7 8 9 | from pyramid.security import Allow
from pyramid.security import Everyone
class Blog(object):
__acl__ = [
(Allow, Everyone, 'view'),
(Allow, 'group:editors', 'add'),
(Allow, 'group:editors', 'edit'),
]
|
また、リソースが永続的である場合、ACLはリソースの*インスタンス*の `` __acl__``属性で指定することができます:
1 2 3 4 5 6 7 8 9 10 11 12 13 | from pyramid.security import Allow
from pyramid.security import Everyone
class Blog(object):
pass
blog = Blog()
blog.__acl__ = [
(Allow, Everyone, 'view'),
(Allow, 'group:editors', 'add'),
(Allow, 'group:editors', 'edit'),
]
|
ACLがリソースのクラスにアタッチされているか、リソース自体のインスタンスにアタッチされているかにかかわらず、その効果は同じです。オブジェクト単位できめ細かなアクセスが必要なコンテンツ管理システムなどのアプリケーションでは、個々のリソースインスタンスをACLで修飾すると便利です(クラスを装飾するのではなく)。
動的ACLは、ACLをリソース上の呼び出し可能にすることによっても可能です。これにより、ACLはインスタンスのプロパティに基づいてルールを動的に生成できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from pyramid.security import Allow
from pyramid.security import Everyone
class Blog(object):
def __acl__(self):
return [
(Allow, Everyone, 'view'),
(Allow, self.owner, 'edit'),
(Allow, 'group:editors', 'edit'),
]
def __init__(self, owner):
self.owner = owner
|
警告
`` __acl__``をプロパティとして書くのは、 `` fget``や `` fset``で起こっている `` AttributeError``が黙って解消されるので、お勧めしません(これはPythonの `` getattr``と `` hasattr`` `行動)。ダイナミックACLの場合は、上記のとおり、単にコールアーブルを使用します。
ACLの要素¶
次に、ACLの例を示します。
1 2 3 4 5 6 7 8 | from pyramid.security import Allow
from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
(Allow, 'group:editors', 'add'),
(Allow, 'group:editors', 'edit'),
]
|
ACLの例は、:data: pyramid.security.Everyone`プリンシパル(文字通り全員を示す特別なシステム定義プリンシパル)がブログを閲覧することを許可され、 `group:editors``プリンシパルがブログに追加して編集する。
ACLの各要素は:term: ACE`またはアクセス制御エントリです。例えば、上記のコードブロックには、 ``(許可、全員、 'ビュー')、 ``(許可、 'グループ:編集者'、 '追加')、 ``許可: 'グループ:編集者'、 '編集') `。
ACEの最初の要素は、data: pyramid.security.Allow、または:data:` pyramid.security.Deny`です。これは、ACEが一致したときに取るアクションを表します。 2番目の要素は:term: `principal`です。 3番目の引数は、パーミッション名のパーミッションまたはシーケンスです。
プリンシパルは通常はユーザーIDですが、認証システムがグループ情報を提供し、有効:term: `認証ポリシー`ポリシーがグループ情報を考慮して記述されている場合は、グループIDでもかまいません。参照:ref: `extend_default_authentication_policies`を参照してください。
ACL内の各ACEは、ACL *で指定された順序で認可ポリシー*によって処理されます。したがって、次のようなACLがあるとします。
1 2 3 4 5 6 7 8 | from pyramid.security import Allow
from pyramid.security import Deny
from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
(Deny, Everyone, 'view'),
]
|
既定の認可ポリシーでは、後でACLにすべてのユーザーにビューのアクセス許可を拒否するACEがあっても、すべてのユーザーに表示許可が許可されます。一方、次のようなACLがある場合は、
1 2 3 4 5 6 7 8 | from pyramid.security import Everyone
from pyramid.security import Allow
from pyramid.security import Deny
__acl__ = [
(Deny, Everyone, 'view'),
(Allow, Everyone, 'view'),
]
|
認可ポリシーは、後でACLにも、すべての人を許可するACEが存在するにもかかわらず、すべての人に表示許可を拒否します。
ACEの3番目の引数は、1つのアクセス権名の代わりに一連のアクセス権名にすることもできます。したがって、単一の `` group:editors``グループにいくつかの異なる許可許可を表す複数のACEを作成するのではなく、これを以下のように単一のACEにすることができます。
1 2 3 4 5 6 7 | from pyramid.security import Allow
from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
(Allow, 'group:editors', ('add', 'edit')),
]
|
特別なプリンシパル名¶
特殊なプリンシパル名は:mod: pyramid.security`モジュールにあります。あなた自身のコードで使用するためにインポートすることができます(例::data: `pyramid.security.Everyone)。
:データ: pyramid.security.Everyone
文字どおり、誰でも、何でも。このオブジェクトは実際にはフードの下の文字列です( `` system.Everyone``)。すべてのユーザー*は、セキュリティポリシーが使用されていなくても、すべての要求中に"Everyone "という名前のプリンシパルです。
:データ: pyramid.security.Authenticated
現在のセキュリティポリシーによって決定された資格情報を持つすべてのユーザー。あなたは"ログインしている"というユーザーと考えるかもしれません。このオブジェクトは実際にはフードの下にある文字列です( `` system.Authenticated``)。
特別な許可¶
特殊なパーミッション名は:mod: `pyramid.security`モジュールにあります。これらは、ACLで使用するためにインポートできます。
:データ: pyramid.security.ALL_PERMISSIONS
特別なACE¶
便宜上、用語: ACE`は:data: pyramid.security.DENY_ALL`のすべてのパーミッションの拒否を表すように定義されています。このACEは、ACLの* last * ACEとして使用され、継承された認可ポリシーが"トラバーサルツリーの検索を中止する"(事実上すべての継承を破棄)するようにしばしば使用されます。例えば、デフォルトの認可ポリシーが有効なときに継承されたACLがどのようなことを言うかもしれないにもかかわらず、特定のリソースに対するビューのアクセス権のみを `` fred``で許可するACLは、次のようになります:
1 2 3 4 | from pyramid.security import Allow
from pyramid.security import DENY_ALL
__acl__ = [ (Allow, 'fred', 'view'), DENY_ALL ]
|
フードの下では、:data: pyramid.security.DENY_ALL ACEは以下のようになります:
1 2 | from pyramid.security import ALL_PERMISSIONS
__acl__ = [ (Deny, Everyone, ALL_PERMISSIONS) ]
|
ACLの継承とロケーション認識¶
default:term: `authorization policy`が設定されていますが、リソースオブジェクトがコンテキストのときにACLを持たない場合は、ACLの* parent が参照されます。そのオブジェクトにACLがない場合、ルートに達して親がなくなるまで its * parentはACL、ad infinitumについて調べられます。
セキュリティ機構がACL継承を実行できるようにするには、リソースオブジェクトは* location-awareness *を提供する必要があります。 * location-awareness *を指定するとは、リソースツリーのルートオブジェクトに `` __name__``属性と `` __parent__``属性が必要です。
1 2 3 | class Blog(object):
__name__ = ''
__parent__ = None
|
`` __parent__``属性と `` __name__``属性を持つオブジェクトは* location-aware *と言います。位置認識オブジェクトは親オブジェクトを指す `` __parent__``属性を定義します。ルートオブジェクトの `` __parent__``は `` None``です。
参考
ロケーション認識を使用する関数のドキュメントについては、:ref: `location_module`も参照してください。
参考
参照:ref: `location_aware`も参照してください。
禁止されたビューの変更¶
:app: Pyramid`が許可拒否のためにビューの呼び出しを拒否したとき、特別な 禁じられた ビューが呼び出されます。箱の外では、この禁止された表示は非常に明白です。ビューの許可が拒否されたときに呼び出されるように、カスタム禁止ビューを作成する方法については、ref: `hooks_chapter`を参照してください:ref: changing_the_forbidden_view`:ref: `hooks_chapter`を参照してください。
ビュー認証エラーのデバッグ¶
あなたの判断でアプリケーションがビューのアクセスを不適切に許可または拒否している場合は、 `` PYRAMID_DEBUG_AUTHORIZATION``環境変数を `` 1``に設定してシェルの下でアプリケーションを起動してください。例えば:
$ PYRAMID_DEBUG_AUTHORIZATION=1 $VENV/bin/pserve myproject.ini
トップレベルのビューレンダリング中に何らかの認可が行われると、認証情報に基づいて認可を許可または拒否されたACEのACEについてコンソール(stderr)にログが記録されます。
この動作は、アプリケーションの設定セクション内で `` pyramid.debug_authorization``キーを `` true``に設定することで、アプリケーションの `` .ini``ファイルで有効にすることもできます。
1 2 3 | [app:main]
use = egg:MyProject
pyramid.debug_authorization = true
|
このデバッグフラグをオンにすると、ブラウザに送信されるレスポンスにはセキュリティデバッグ情報も含まれます。
強制的な認証失敗のデバッグ¶
:meth: pyramid.request.Request.has_permission APIは、ビュー関数内のセキュリティを必須にチェックするために使用されます。実質的にブーリアンであるオブジェクトのインスタンスを返します。しかし、これらのオブジェクトは生の `` True``や False``オブジェクトではなく、許可が拒否された理由についての情報が添付されています。オブジェクトは、data: `pyramid.security.ACLAllowed、:data:` pyramid.security.ACLDenied`、:data: pyramid.security.Allowed、または:data:` pyramid.security.Denied`のいずれかです。 :ref: security_module`に記述されています。最小限でも、これらのオブジェクトは ` msg``属性を持ちます。これは、なぜパーミッションが拒否されたのかを示す文字列です。 :meth: `〜pyramid.request.Request.has_permission`への呼び出しが失敗したときに、デバッガやprint文でこの情報を調べることはしばしば役に立ちます。
デフォルトの認証ポリシーの拡張¶
Pyramidには、アプリケーションで使用するためのいくつかの認証ポリシーが組み込まれています。利用可能なポリシーについては、mod: `pyramid.authentication`を参照してください。要求間で認証資格情報を追跡するメカニズムは異なりますが、アプリケーションとのインターフェイスはほとんど同じです。
あなたの上で学んだ:ref: assigning_acls。それぞれ:term: principal`は:term: ACL`で使用され、:meth: pyramid.interfaces.IAuthenticationPolicy.effective_principals`から返されたリストと照合されます。同様に、:meth: `pyramid.request.Request.authenticated_userid`は:meth: pyramid.interfaces.IAuthenticationPolicy.authenticated_userid`にマップします。
これらの値は、デフォルトの認証ポリシーをサブクラス化することで制御できます。例えば:class: pyramid.authentication.AuthTktAuthenticationPolicy`をサブクラス化し、クッキーの値を盲目的に信頼することを避けるために:term: userid`が有効であることを確認する前に、データベースに問い合わせる特別な機能を定義します。クッキーがまだ有効だが、ユーザーがアカウントを削除した場合)次に、その:term: userid`を使って、 `effective_principals``を、そのユーザのグループや他の状態に関する情報で補強します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from pyramid.authentication import AuthTktAuthenticationPolicy
class MyAuthenticationPolicy(AuthTktAuthenticationPolicy):
def authenticated_userid(self, request):
userid = self.unauthenticated_userid(request)
if userid:
if request.verify_userid_is_still_valid(userid):
return userid
def effective_principals(self, request):
principals = [Everyone]
userid = self.authenticated_userid(request)
if userid:
principals += [Authenticated, str(userid)]
return principals
|
ほとんどの場合、 `` authenticated_userid``と `` effective_principals``はアプリケーション固有ですが、 `` unauthenticated_userid``、 `` remember``、 `` forget``は一般的であり、連続したリクエスト。
独自の認証ポリシーの作成¶
:app: Pyramid`には、いくつかの便利なセキュリティポリシーが付属しています(mod: pyramid.authentication`参照)。ただし、ユーザーの認証方法の「水平および垂直」を制御する場合は、独自の認証ポリシーを作成する必要があります。そうすることは、次のインターフェースを実装するもののインスタンスを作成することです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | class IAuthenticationPolicy(object):
""" An object representing a Pyramid authentication policy. """
def authenticated_userid(self, request):
""" Return the authenticated :term:`userid` or ``None`` if
no authenticated userid can be found. This method of the
policy should ensure that a record exists in whatever
persistent store is used related to the user (the user
should not have been deleted); if a record associated with
the current id does not exist in a persistent store, it
should return ``None``.
"""
def unauthenticated_userid(self, request):
""" Return the *unauthenticated* userid. This method
performs the same duty as ``authenticated_userid`` but is
permitted to return the userid based only on data present
in the request; it needn't (and shouldn't) check any
persistent store to ensure that the user record related to
the request userid exists.
This method is intended primarily a helper to assist the
``authenticated_userid`` method in pulling credentials out
of the request data, abstracting away the specific headers,
query strings, etc that are used to authenticate the request.
"""
def effective_principals(self, request):
""" Return a sequence representing the effective principals
typically including the :term:`userid` and any groups belonged
to by the current user, always including 'system' groups such
as ``pyramid.security.Everyone`` and
``pyramid.security.Authenticated``.
"""
def remember(self, request, userid, **kw):
""" Return a set of headers suitable for 'remembering' the
:term:`userid` named ``userid`` when set in a response. An
individual authentication policy and its consumers can
decide on the composition and meaning of **kw.
"""
def forget(self, request):
""" Return a set of headers suitable for 'forgetting' the
current user on subsequent requests.
"""
|
その後、そのクラスのインスタンスを設定時に:class: `〜pyramid.config.Configurator.set_authentication_policy`メソッドに渡して使用することができます。
独自の認証ポリシーの作成¶
認可ポリシーは、ユーザーが認証された後にアクセスを許可または拒否するポリシーです。 Most:app: Pyramid`アプリケーションはデフォルト:class: pyramid.authorization.ACLAuthorizationPolicy`を使用します。
しかし、場合によっては、デフォルト:class: `〜pyramid.authorization.ACLAuthorizationPolicy`以外の別の認証ポリシーを使用できるようにすると便利です。例えば、アプリケーションがterm: `ACL`オブジェクトに関係しない認証機構を使用することを可能にする代替の認証ポリシーを構築することが望ましいかもしれません。
:app: `Pyramid`はデフォルトの認証ポリシーが1つしかないので、別のものを使用するには独自のものを作成する必要があります。独自の認可ポリシーを作成して使用することは、次のインターフェースを実装するオブジェクトのインスタンスを作成することです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class IAuthorizationPolicy(object):
""" An object representing a Pyramid authorization policy. """
def permits(self, context, principals, permission):
""" Return ``True`` if any of the ``principals`` is allowed the
``permission`` in the current ``context``, else return ``False``
"""
def principals_allowed_by_permission(self, context, permission):
""" Return a set of principal identifiers allowed by the
``permission`` in ``context``. This behavior is optional; if you
choose to not implement it you should define this method as
something which raises a ``NotImplementedError``. This method
will only be called when the
``pyramid.security.principals_allowed_by_permission`` API is
used."""
|
その後、このクラスのインスタンスを構成時に:class: `〜pyramid.config.Configurator.set_authorization_policy`メソッドに渡して使用することができます。
シークレット・シェアリングに対する警戒¶
"秘密"は、Pyramidのさまざまなコンポーネントによって必要とされます。たとえば、以下の:term: 認証ポリシー`は秘密の値 ` seekrit`` ::を使用します。
authn_policy = AuthTktAuthenticationPolicy('seekrit', hashalg='sha512')
A:term: `session factory`には秘密が必要です:
my_session_factory = SignedCookieSessionFactory('itsaseekreet')
複数のPyramidサブシステムに同じ秘密を使用するのは魅力的です。たとえば、上記で定義した認証ポリシーとセッションファクトリの両方の秘密として、 `` seekrit``という値を使うことができます。どちらの場合も、これらの秘密はデータのペイロードに署名するために使用されるため、これは悪い考えです。
署名の目的でアプリケーションの2つの異なる部分に同じ秘密を使用すると、攻撃者が選択した平文を署名することが可能になり、攻撃者がペイロードの内容を制御できるようになります。 2つの異なるサブシステムにわたって秘密を再使用すると、署名のセキュリティがゼロになる可能性があります。鍵は、攻撃者が選択した平文を提供する可能性のある別のコンテキストで再使用しないでください。
クロスサイトリクエスト偽造攻撃の防止¶
`クロスサイトリクエスト偽造<https://en.wikipedia.org/wiki/Cross-site_request_forgery>攻撃は、攻撃者のウェブサイトからリンクされているか、またはウェブサイトに埋め込まれているため、ウェブサイトにログインしているユーザーが誤ってURLを読み込んでしまう現象です。 URLがデータを変更または削除するURLである場合、その結果は致命的となる可能性があります。
これらの攻撃のほとんどは、ブラウザに一意のトークンを発行してから、安全でない可能性があるすべての要求にそのトークンが存在することを要求することで回避できます。 :app: `Pyramid`は、CSRFトークンを作成して確認するための機能を提供します。
デフォルトでは、app: Pyramid`には、セッションベースのCSRF実装であるclass: pyramid.csrf.SessionCSRFStoragePolicy`があります。それを使用するには、:ref: using_the_default_session_factory`または:ref: using_alternate_session_factories`で説明されているように、まず:term: session factory`を有効にする必要があります。代わりに、cookieベースの実装を使用することもできます:class: `pyramid.csrf.CookieCSRFStoragePolicy`これは、各ユーザにセッションを必要としないため、いくつかの柔軟性を提供します。独自の:class: `pyramid.interfaces.ICSRFStoragePolicy`の実装を定義し、:meth: pyramid.config.Configurator.set_csrf_storage_policy`ディレクティブで登録することもできます。
例えば:
from pyramid.config import Configurator
config = Configurator()
config.set_csrf_storage_policy(MyCustomCSRFPolicy())
`` csrf.get_csrf_token``メソッドの使用¶
現在のCSRFトークンを取得するには、:data: `pyramid.csrf.get_csrf_token`メソッドを使用します。
from pyramid.csrf import get_csrf_token
token = get_csrf_token(request)
`` get_csrf_token() ``メソッドは単一の引数、つまり要求を受け入れます。 CSRF * token *文字列を返します。 `` get_csrf_token() ``または `` new_csrf_token() ``が以前にこのユーザに対して呼び出された場合、既存のトークンが返されます。以前にこのユーザーに対してCSRFトークンが存在しなかった場合、新しいトークンがセッションに設定され、返されます。新しく作成されたトークンは不透明でランダム化されます。
テンプレートで `` get_csrf_token``グローバルを使う¶
テンプレートには、グローバルに挿入された `` get_csrf_token() ``メソッドがあり、ビューコードを変更せずに現在のトークンを取得できます。このメソッドは引数を取らず、CSRFトークン文字列を返します。返されたトークンは、昇格された特権を必要とするメソッドに投稿するフォームの隠しフィールドの値として使用することも、AJAX要求の要求ヘッダーとして供給することもできます。
たとえば、CSRFトークンを隠しフィールドとして含めます。
<form method="post" action="/myview">
<input type="hidden" name="csrf_token" value="${get_csrf_token()}">
<input type="submit" value="Delete Everything">
</form>
または、これをjQuery AJAXリクエストのヘッダーとしてインクルードします。
var csrfToken = "${get_csrf_token()}";
$.ajax({
type: "POST",
url: "/myview",
headers: { 'X-CSRF-Token': csrfToken }
}).done(function() {
alert("Deleted");
});
要求を受け取るURLのハンドラは、正しいCSRFトークンが供給されることを要求する必要があります。
`` csrf.new_csrf_token``メソッドの使用¶
明示的に新しいCSRFトークンを作成するには、 `` csrf.new_csrf_token() ``メソッドを使用します。これは、既存のCSRFトークンをクリアし、新しいCSRFトークンを作成し、トークンをユーザに設定し、トークンを返すだけで、 `` csrf.get_csrf_token() ``とだけ異なります。
from pyramid.csrf import new_csrf_token
token = new_csrf_token(request)
注釈
テンプレートから新しいCSRFトークンを強制することはできません。 CSRFトークンを再生成する場合は、ビューコードでそれを行い、新しいトークンをコンテキストの一部として返します。
CSRFトークンを手動で確認する¶
リクエスト処理コードでは、:func: pyramid.csrf.check_csrf_token`を使用して、CSRFトークンの存在と有効性をチェックできます。トークンが有効であれば ` True``を返し、そうでなければ `` HTTPBadRequest``を送出します。オプションで、 `` raises = False``を指定すると、例外を発生させる代わりにチェックが `` False``を返すようにすることができます。
デフォルトでは、 `` csrf_token``という名前のPOSTパラメータか `` X-CSRF-Token``というヘッダがあるかどうかを調べます。
from pyramid.csrf import check_csrf_token
def myview(request):
# Require CSRF Token
check_csrf_token(request)
# ...
CSRFトークンの自動確認¶
バージョン 1.7 で追加.
:app: `Pyramid`は、RFC2616で定義されているような安全でないメソッドで、CSRFトークンを自動的にチェックします。他の要求は手動でチェックすることができます。この機能は、:meth: `pyramid.config.Configurator.set_default_csrf_options`指示文を使用してアプリケーションに対してグローバルにオンにすることができます。例えば:
from pyramid.config import Configurator
config = Configurator()
config.set_default_csrf_options(require_csrf=True)
CSRF検査は、 `` require_csrf``ビューオプションを使用してビュー単位で明示的に有効または無効にすることができます。 `` True``または `` False``の値は、 `` set_default_csrf_options``で設定されたデフォルトを上書きします。例えば:
@view_config(route_name='hello', require_csrf=False)
def myview(request):
# ...
CSRFチェックがアクティブな場合、 `` set_default_csrf_options``によってオーバーライドされない限り、提供されたCSRFトークンを見つけるために使用されるトークンとヘッダは、それぞれ `` csrf_token``と `` X-CSRF-Token``です。トークンは、送信されたフォーム本体である `` request.POST``の値と照合されます。この値が存在しない場合、ヘッダーがチェックされます。
トークンベースのCSRFチェックに加えて、リクエストがHTTPSを使用している場合、自動CSRFチェックはリクエストのリファラーをチェックして、信頼できる発信元の1つに一致することを確認します。デフォルトでは、信頼できる唯一の原点は現在のホストですが、 `` pyramid.csrf_trusted_origins``をドメイン名のリスト(およびそれらが非標準の場合はポート)に設定することによって、追加の起点を設定することができます。ドメインのリストのホストが `` .``で始まっている場合、 `` .``のないドメインと同様に、すべてのサブドメインが許可されます。
CSRFチェックが失敗した場合、class: pyramid.exceptions.BadCSRFToken`または:class: pyramid.exceptions.BadCSRFOrigin`例外が送出されます。この例外は:term: exception view`によって捕捉され、処理されるかもしれませんが、デフォルトでは、 `400 Bad Request``応答がクライアントに送られます。
ビュー・プレディケートによるCSRFトークンのチェック¶
バージョン 1.7 で撤廃: `` require_csrf``オプションを使うか、:ref: auto_csrf_checking`を読んで:class: pyramid.exceptions.BadCSRFToken`例外を発生させてください。
特定のビューに対して有効なCSRFトークンを要求する便利な方法は、ビューの述語として `` check_csrf = True``を含めることです。参照:meth: pyramid.config.Configurator.add_view。
@view_config(request_method='POST', check_csrf=True, ...)
def myview(request):
...
注釈
CSRFトークンの不一致は、他の述語ミスのように扱われ、ビューを見つけられない場合、述語システムは `` HTTPBadRequest``の代わりに `` HTTPNotFound``を発生させるので、 `` check_csrf = True``振る舞いは:func: `pyramid.csrf.check_csrf_token`とは異なります。