高度な ACL のコンセプト

この章の目的は、 ACL システムの詳細と、その背景となる設計決定について説明することです。

設計コンセプト

Symfony2 のオブジェクトインスタンスのセキュリティは、アクセス制御リストのコンセプトに基づいています。全てのドメインオブジェクトの インスタンス は、独自の ACL を持ってます。 ACL インスタンスは、実際のアクセス可否の決定をするアクセス制御エンティティ(ACEs)の詳細なリストを持っています。 Symfony2 の ACL システムには、次の2つの目的があります。

  • 効率的にドメインオブジェクトに対するたくさんの ACLs/ACEs を取り出し、変更する方法を提供すること
  • あるユーザがドメインオブジェクトに対して動作を行うことができるか、簡単に決定をする方法を提供すること

まず最初のポイントとして、 Symfony2 の ACL システムの主な性能は ACLs/ACEs の取り出しのパフォーマンスが良いことです。このハイパフォーマンス性能は ACL がたくさんの ACEs を持っていたり、ツリー構造から継承していた際などに特に重要になります。そのため、データベース接続にどの ORM も使用しません。しかし、デフォルトの実装は Doctrine DBAL を直接使用して接続を行います。

オブジェクトアイデンティティ(Object Identities)

ACL システムはドメインオブジェクトと完全に切り離されています。同じデータベースに格納する必要もありませんし、同じサーバである必要もありません。この切り離しのために、 ACL システムではオブジェクトはオブジェクトアイデンティティ(Object Identity)オブジェクトを介して表されます。毎回、ドメインオブジェクトの ACL を取り出す際に、次の処理のために、このオブジェクトアイデンティティを ACL のプロバイダに渡します。

セキュリティアイデンティティ(Security Identities)

セキュリティアイデンティティは、オブジェクトアイデンティティと類似していますが、ユーザやアプリケーションの権限を表してます。それぞれの権限やユーザは独自のセキュリティアイデンティティを持っています。

データベースのテーブル構造

デフォルトの実装は、以下にあるように5つのデータベースのテーブルを使用します。テーブルは、典型的なアプリケーションで列の大きさの小さい順で並べてあります。

  • acl_security_identities: このテーブルは、全ての ACE を持つセキュリティアイデンティティ(SID)を記録します。デフォルトの実装では、 RoleSecurityIdentityUserSecurityIdentity の2つのアイデンティティがあります。
  • acl_classes: このテーブルは、他のテーブルから参照できるようにクラス名をユニークな id でマップします。
  • acl_object_identities: このテーブルの各列は、単独のドメインオブジェクトインスタンスを表します。
  • acl_object_identity_ancestors: このテーブルは、とても効率的な方法で ACL の祖先を全て決定できるようにします。
  • acl_entries: このテーブルは、全ての ACE を含みます。ほとんどの場合、このテーブルが最も列が大きくなります。パフォーマンスに影響を与えることなく数千万件含むことができます。

アクセス制御エンティティ(ACE)のスコープ

アクセス制御エンティティは、異なるスコープを持つことができます。 Symfony2 では、基本的に2つのスコープを持つことなります。

  • Class-Scope: エンティティを、全てのオブジェクトを同じクラスに適用します
  • Object-Scope: エンティティを、単体で使うスコープで、特定のオブジェクトのみにに適用します

オブジェクトの特定のフィールドのみに ACE を適用する必要があるときもあります。例えば ID のみを管理者に見えるようにして、他の人には見せないようにするとしましょう。この問題を解決するに、サブスコープをさらに2つ追加しました。

  • Class-Field-Scope: エンティティは、全てのオブジェクトを同じクラスに適用しますが、オブジェクトの特定のフィールドのみです
  • Object-Field-Scope: エンティティは、特定のオブジェクトに適用しますが、そのオブジェクトの特定のフィールドのみです

認証前の決定

メソッドやセキュアなアクションが実行される前の決定である認証前決定では、実績があり権限に基づいた認証決定に使用される AccessDecisionManager サービスを使用します。権限と同じように、 ACL システムは異なるパーミッションを調べるための新しい属性を追加します。

ビルトインされているパーミッションマップ

属性 目的 整数値のビットマスク
VIEW ドメインオブジェクトを参照 できるか否か VIEW, EDIT, OPERATOR MASTER, or OWNER
EDIT ドメインオブジェクトを変更 することができるか否か EDIT, OPERATOR, MASTER, or OWNER
CREATE ドメインオブジェクトを作成 できるか否か CREATE, OPERATOR, MASTER, or OWNER
DELETE ドメインオブジェクトを削除 できるか否か DELETE, OPERATOR, MASTER, or OWNER
UNDELETE 削除されたドメインオブジェ クトを元に戻すことができる か否か UNDELETE, OPERATOR, MASTER, or OWNER
OPERATOR ユーザが上記のアクションを 全て行うことができるか否か OPERATOR, MASTER, or OWNER
MASTER ユーザが上記のアクションを 全て行うことができるか否か 、また、他ユーザに上記のア クションを与えることができ るか否か MASTER, or OWNER
OWNER ドメインオブジェクトのオー ナーか否か。オーナーは、全 てのアクションを行うことが でき、 かつ マスター権限 とオーナー権限を与えること ができる OWNER

パーミッション属性 vs. パーミッションビットマスク

AccessDecisionManager の属性のように、権限が使用をします。実際にこれらの属性は整数値のビットマスクの集合なります。整数値のビットマスクは、内部的に ACL システムで使用され、効率的にユーザのパーミッションをデータベースに保存します。そしてとても効率の良いビットマスクオペレーションによってアクセス権限をチェックします。

拡張性

上記のパーミッションマップは、決して静的なものではなく、理論的には完全に置き換えが可能です。しかし、そうすることで問題が起きやすく、また他のバンドルとの兼ね合いもあるため、このまま使用することを推奨します。

認証後決定

認証後決定は、セキュアメソッドが実行された後に行われ、そのメソッドによって返ってきたドメインオブジェクトを含むことになります。起動プロバイダは、ドメインオブジェクトを返す前に変更、フィルターすることができます。

現時点の PHP 言語の制約のため、コアセキュリティのコンポーネントに組み込まれた認証後の機能はありません。しかし、 JMSSecurityExtraBundle には認証後の機能があります。そのやり方の詳細は JMSSecurityExtraBundle のドキュメントを参照してください。

認証決定へのプロセス

ACL クラスはセキュリティアイデンティティが必要なビットマスクを持っているかを決定する2つのメソッドを提供します。 isGrantedisFieldGranted です。 ACL がこれらのメソッドで認証リクエストを受け取ると、 PermissionGrantingStrategy の実装にリクエストを移譲します。 PermissionGrantingStrategy を使うと、ACL クラス自体を変更しなくても、アクセス可否の決定をすることができます。

PermissionGrantingStrategy は、まずあなたのオブジェクトスコープの ACE を全て調べ、何も適用できなければ。クラススコープお ACE を調べます。それでも適用がなければ、このプロセスが親の ACL の ACE にとして繰り返されます。親の ACL にも無い際には例外が投げられます。