私は次のスキームを使用します。ほとんどのユーザーパーミッションチェックは、2つの一般的なケースに分けることができます。
- パラメータアクションを確認せずにユーザーロールに基づいてコントローラーアクションへのユーザーアクセスが呼び出される、
- 特定のユーザーと特定のモデルの間の任意のロジックまたは関係に基づいて、モデルへのユーザーアクセス。
通常、属性のチェックなしでのコントローラーアクションへのアクセスは、MVCフレームワークで実装されます。これはまったく簡単です。ルールを定義し、ユーザーが役割を持ちます。ユーザーがルールでその役割を検索するアクションの許可を持っていることを確認するだけです。
特定のモデルへのユーザーアクセスは、モデルで定義する必要があります。(アクターは基本ユーザークラスです。顧客、売り手、またはゲストのいずれかであると想定します。)
interface ICheckAccess
{
public function checkAccess(Actor $actor, $role);
}
class SomeModel implements ICheckAccess
{
public function checkAccess(Actor $actor, $role)
{
// Your permissions logic can be as sophisticated as you want.
}
}
そのロジックをモデルに配置すると、いくらかの利益がもたらされます。アクセスチェックメソッドを継承できます。追加のクラスを作成する必要はなく、一般的なOOPの利点を使用できます。
次に、アクセスチェックを単純化するために、単純化と適切なスタイルのために、ほとんど常に既に実装されているいくつかの仮定を採用します。
- 通常、コントローラーはいくつかのモデルクラスに関連しています。
- アクセスがチェックされるアクションは、単一のモデルIDをパラメーターとして受け取ります。
- このパラメーターは、基本コントローラークラスのメソッドから常に均一にアクセスできます。
- idアクションが実行するモデルに対応するコントローラーにアクションが配置されます。
これらの仮定により、モデルIDを使用するアクションを特定のモデルインスタンスに関連付けることができます。実際、ほとんどのアクションは、上記の仮定に合わせて簡単に変換および移動できます。
次に、いくつかの基本抽象コントローラークラスを定義して継承する必要があります。
abstract class ModelController
{
// Retrieve model from database using id from action parameter.
public abstract function loadModel($id);
// Returns rules for user role to pass to SomeModel::checkAccess()
// Something like array('view' => 'viewer', 'delete' => 'owner', 'update' => 'owner')
public abstract function modelRules();
public abstract fucntion getIdParameter();
public function filterModelAccess()
{
$id = $this->getIdParameter();
if(!$this->checkModelAccess($id))
throw new HttpException(403);
}
public function checkModelAccess($id)
{
$model = $this->loadModel($id);
$actor = My::app()->getActor();
$rules = $this->modelRules();
$role = $rules[My::app()->getActionName()];
return $model->chechAccess($actor, $role);
}
}
メニューを作成し、リンクを表示するかどうかを決定するときに、SomeController :: checkModelAccess($ id)メソッドを呼び出すことができます。