Io uso il seguente schema.
Vale la pena dire che la maggior parte dei controlli delle autorizzazioni utente può essere suddivisa in due casi generali:
- accesso utente all'azione del controller in base al ruolo utente senza controllo
l'azione dei parametri è chiamata con,
- accesso utente al modello basato su qualsiasi logica o relazione tra
particolare utente e modello particolare.
L'accesso all'azione del controller senza il controllo degli attributi viene solitamente implementato nei framework MVC. Questo è semplice: definite le regole, i vostri utenti hanno un ruolo. Devi semplicemente controllare che l'utente abbia il permesso di agire per trovare il suo ruolo nelle regole.
L'accesso utente a un modello particolare dovrebbe essere definito nel modello. (L'attore è una classe utente di base. Supponiamo che possa essere cliente, venditore o ospite.)
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.
}
}
Inserire questa logica nel modello porta qualche profitto. Il metodo di controllo dell'accesso può essere ereditato, non è necessario creare classi aggiuntive, è possibile utilizzare i vantaggi OOP generali.
Successivamente, per semplificare il controllo degli accessi, prendiamo alcune ipotesi che sono quasi sempre implementate già per semplicità e buon stile:
- solitamente i controller sono correlati ad alcune classi di modelli;
- le azioni che sono verificate per l'accesso prendono come ID un singolo modello come parametro;
- questo parametro è sempre accessibile in modo uniforme dal metodo della classe del controller di base;
- l'azione viene inserita nel controller corrispondente al modello che prende l'azione id.
Con questi presupposti, le azioni che utilizzano l'id del modello possono essere associate a una particolare istanza di modello. In effetti, la maggior parte delle azioni può essere facilmente trasformata e spostata per soddisfare le ipotesi sopra indicate.
Quindi, alcune classi di controller astratto di base dovrebbero essere definite ed ereditate.
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);
}
}
Puoi chiamare il metodo SomeController :: checkModelAccess ($ id) quando costruisci i menu e decidi se mostrare qualche link.