Come aggiungere i controlli delle autorizzazioni "dopo il fatto"

2

Ho un gran numero di classi PHP che eseguono la logica di business della mia applicazione, ad es.

class FileMaker{
  public function makeFile(){
    //some code here to make a file
  }
}

Ora ho bisogno di aggiungere controlli delle autorizzazioni a loro. Voglio evitare di dover copiare / incollare $ this- > checkPermissions () o simili in ogni metodo in ogni classe. Qual è il modo migliore per raggiungere questo obiettivo?

Stavo pensando ad un tipo di schema di decorazione che potrebbe aggiungere controlli delle autorizzazioni, ad es.

//decorator that can be used to check permissions
class PermissionsDecorator{
    private $ob;

    public function __construct($ob){
        $this->ob = $ob;
    }

    //magic method which is called when any function is called
    public function __call($name,$arguments){
        if($this->hasPermission(get_class($this->ob), $name)){
            call_user_func_array(array($this->ob,$name),$arguments);
        }else{
            throw new Exception('You do not have permission to perform this action.');
        }
    }

    public function hasPermission($class,$method){
        echo 'does the user have permission on '.$class.'->'.$method.'?<br/>';

        //do some logic here to work out whether the user has permission
        return true;
    }
}

Il decoratore sopra potrebbe applicarsi a tutte le classi perché usa il metodo magico __call, piuttosto che specificare i metodi esatti da chiamare. Quindi potrei usare codice come:

$fm = new PermissionsDecorator(new FileMaker());

Però mi sembra un po '"hacky". C'è un modo standard per farlo? O dovrò semplicemente copiare / incollare i permessi di controllo ovunque?

    
posta user1578653 03.02.2015 - 11:35
fonte

1 risposta

3

Se la quantità di lavoro che dovresti spendere al refactoring per una trasparente implementazione dell'autenticazione nei tuoi controllori è davvero assolutamente proibitiva, un decoratore funzionerà.

La ragione per cui dovrebbe sembrare un po '"hacky" è perché fare affidamento su metodi magici rende la funzionalità un po' opaca (i metodi magici, così come call_user_func hanno anche delle penalizzazioni prestazionali, ma di solito sono trascurabili) e perché i decoratori non sono " Le migliori pratiche quando ciò che aggiungono è qualcosa che è necessario affinché il decore funzioni come previsto.

Il modo più trasparente, sicuro e flessibile per farlo (se sono davvero i singoli oggetti / metodi che devono controllare l'autenticazione, che dubito - vedi sotto) sarebbe quello di implementare un pattern di strategia . Nel costruttore di classi le cui istanze devono eseguire l'autenticazione, è necessario un oggetto (ad esempio DefaultUserAuthenticator ) che soddisfi l'interfaccia progettata per la strategia (ad esempio IUserAuthenticator ). Un riferimento all'autenticatore concreto verrebbe archiviato in ogni classe (PHP assegna automaticamente gli oggetti per riferimento) e quindi, sì, dovresti chiamare il metodo di autenticazione dell'autenticatore referenziato localmente ovunque sia davvero necessario autenticarlo.

Ma se si esegue sempre immediatamente una richiesta di esecuzione di una determinata funzione all'oggetto e al metodo che esegue la funzione, e quindi si deve controllare l'autorizzazione dell'utente in ogni singolo metodo / oggetto, sembra che questo potrebbe essere l'effettivo problema.

Quando gestisci la richiesta e decidi cosa fare con essa, dovresti controllare il permesso come "alto" nell'albero delle decisioni il più possibile, per evitare esattamente la situazione in cui ti trovi ora. Quindi potresti avere un front controller / controller di pagina / un servizio di supporto che delega gli oggetti specifici solo dopo che l'utente è stato autenticato.

Se stai pensando di utilizzare un modello decoratore, significa che il metodo di autenticazione non varia con ogni oggetto / metodo. Come tale, dovresti essere in grado di controllare il permesso una volta, quindi delegare a un gestore di eccezioni o all'oggetto la cui responsabilità è quella di eseguire effettivamente la funzione richiesta .... i singoli oggetti e metodi non dovrebbero aver bisogno di farlo.

    
risposta data 03.02.2015 - 23:22
fonte

Leggi altre domande sui tag