Best practice PHP routing mvc

7

Ho un framework MVC personalizzato che si trova in uno stato di evoluzione costante. C'è un dibattito di lunga data con un collaboratore su come dovrebbe funzionare il routing. Considerando la seguente struttura di directory:

/core/Router.php
/mvc/Controllers/{Public controllers}
/mvc/Controllers/Private/{Controllers requiring valid user}
/mvc/Controllers/CMS/{Controllers requiring valid user and specific roles}

La domanda è: "Dove deve essere stabilita l'autenticazione dell'utente corrente: nel router, quando si sceglie quale controller / directory caricare, o in ogni controller?"

Il mio argomento è che al momento dell'autenticazione nel Router, viene creato un Controller Errori al posto del Controller richiesto, che ti informa del tuo contrattempo; E la struttura della directory indica chiaramente l'autenticazione richiesta.

Il suo argomento è che un router dovrebbe fare routing e solo routing. Lasciare al controller il modo di gestirlo caso per caso. Questo è più modulare e consente una maggiore flessibilità nel caso in cui le modifiche debbano essere apportate dal router.

Il link ti ha alluso, ma l'argomento era di natura diversa .

Anche i suggerimenti alternativi sarebbero ben accetti.

    
posta jweatherby 08.10.2013 - 22:44
fonte

3 risposte

2

Vorrei andare con i tuoi colleghi a suggerire di lasciare il router per fare il suo dovere e non assumersi altre responsabilità. Penso che sia una buona pratica di programmazione e aiuterebbe gli altri a capire lo stesso.

Ora, per i controllori, suggerisci di andare avanti e utilizzare l'ereditarietà. Avere un controller padre, Base_Controller, che può fare tutte le faccende che è comune a tutti i controller. Da Base, ottieni Secure_Controller e NonSecure_Controller, che fa come afferma il nome.

Puoi sempre lanciare un'eccezione dal controller, che può essere gestita da ganci per visualizzare con garbo la vista.

    
risposta data 09.10.2013 - 07:30
fonte
2

Avrei un altro componente intermedio che determina i diritti di accesso. Questo componente può avere un insieme di mappature dei ruoli utente alle risorse, dove i controllori e / o le azioni sono le risorse. L'esecuzione andrebbe quindi in questo modo:

Router -> Authorization -> Controller

Router: determines which controller and action to execute

Auth: find out which user role is logged in and check
if the user has access to the controller/action,
if not, throw an exception that will get caught by the error handler,
or redirect to login page for guests, or whatever

Controller: if the authorization component didn't complain, do work as usual

Se vuoi essere elegante, puoi usare i commenti e le riflessioni di php doc per annotare i tuoi metodi e controller sul posto invece di avere un grande elenco di risorse permesse per i ruoli degli utenti. Qualcosa come:

class Controller {
    /**
     * @allow({'admin','user'})
     * @prevent({'guest'})
     */
    public function someAction(){}
}

Il componente auth può quindi leggere le annotazioni per determinare i diritti di accesso, invece di avere una grande lista di mappature delle risorse di ruolo >

    
risposta data 09.10.2013 - 09:18
fonte
2

Ecco un'idea. Tecnicamente, forse entrambi non sono corretti. Forse il posto migliore per lo stato di accesso dell'utente e il ruolo da convalidare è un'istanza concreta di una classe Validator .

Questo fa sorgere la domanda: cosa farebbe un ControllerValidator nello scenario oltre a verificare se un utente ha effettuato l'accesso? Potrebbe testare cinque cose fondamentali su una richiesta HTTP da derivare se si tratta di una richiesta ragionevolmente buona o probabilmente di un attacco malevolo.

1) Ingressi minimi (sono stati inviati abbastanza controlli HTML?)

2) Ingressi massimi (sono stati inviati troppi controlli HTML?)

3) Input corretti (i controlli HTML hanno inviato quelli giusti?)

4) Codifica corretta (Tipicamente, è la codifica UTF-8, ma è ciò che vuoi / hai bisogno?). Questo controllo dovrebbe avere la sua classe di validatore di specialità. Inietti un'istanza di questo oggetto in tutti gli oggetti ControllerValidator .

5) Dimensioni di input massime (c'è qualche input oltre la dimensione accettabile che avrebbe dovuto arrivare fino a questo punto?).

Quindi, la risposta è che i controllori dovrebbero controllare l'utente e il ruolo (perché è rilevante per la richiesta HTTP, che è il portatore del comando finale). Ricorda, la definizione di un URL HTTP consente l'autenticazione dell'utente. Quindi, controllare l'utente come parte della richiesta è un'attività legittima, anche se non si sta utilizzando l'autenticazione HTTP. La verifica del ruolo è semplicemente un'estensione dell'autenticazione dell'utente.

Ora, questo diagramma UML è solo un abstract. Tuttavia, cattura l'essenza di controllare l' intento di una richiesta HTTP (richiesta in buona fede o chiaramente malevola). Passano tutti i test di un ControllerValidator oppure la richiesta viene rifiutata e terminata.

Tuttavia, osservando le tue esigenze, ci sarebbe una differenza tra PrivateControllerValidator e CMSControllerValidator . Ai primi non sarebbe permesso di fare il controllo dei ruoli. È così che vuoi davvero che sia? Mi sembra che un CMSControllerValidator sia un PrivateControllerValidator . Sei sicuro che un'istanza di PrivateControllerValidator mai debba utilizzare il controllo del rotolo?

Aggiornamento : se disponi di un URL server Web di riscrittura e una classe Router , inizialmente devi eseguire solo i cinque test precedenti per gli aspetti correlati alle intestazioni delle richieste HTTP. Una volta che hai testato abbastanza per inviare dati a Router , puoi fare convalide specifiche della pagina nel modello (in PHP, questo include la convalida di $ _POST, $ _FILES, $ _GET, $ _COOKIE, o qualsiasi altra cosa).

    
risposta data 14.07.2018 - 09:08
fonte

Leggi altre domande sui tag