Permessi a livello di dati a grana fine su un'API RESTful laravel

2

Il problema:

Vogliamo limitare l'accesso alle proprietà restituite dai nostri servizi.

Dettagli:

Abbiamo permessi a livello di percorso che funzionano senza problemi.

Per un utente che può visualizzare /product/{id} , ad esempio, quell'utente potrebbe o meno avere l'autorizzazione per visualizzare la proprietà purchasePrice . (se non dispongono dell'autorizzazione, potrebbe essere vuoto o non esistere nella risposta JSON). Di default laravel restituisce l'intero record quando si carica il modello.

Quello che abbiamo provato:

Al momento stiamo popolando in modo dinamico $visible[] in base alle autorizzazioni e abbiamo un elenco di tutti i campi e quale autorizzazione è richiesta per leggere / scrivere.

La mia domanda:

C'è un modo migliore per farlo? Stiamo reinventando la ruota o sembra un approccio ragionevole?

    
posta mkaatman 24.02.2016 - 19:56
fonte

2 risposte

1

Separa le tue entità dal tuo modello di risposta API. Questo è un caso di SRP (Single Responsibility Principle): il compito delle tue entità è di rendere conveniente l'accesso ai DB. Stai aggiungendo altre due responsabilità, violando lo SRP:

  • imposizione delle autorizzazioni
  • funge da interfaccia pubblica

Ciò significa che ci sono due parti per questa risposta.

con un'API pubblica

Un'API pubblica deve essere stabile e retrocompatibile a meno che non venga dichiarata ai tuoi utenti nel modo più esplicito possibile . Ciò significa che qualsiasi cambiamento nella base di codice che modifica l'API pubblica dovrebbe essere attentamente controllato per la compatibilità all'indietro prima di rilasciarlo alla produzione. Con il tuo approccio attuale, farai molto fatica a farlo: dì che vuoi rinominare una proprietà della tua entità. Bene, l'hai fatto, il tuo IDE ha preso tutti gli usi e li ha rinominati. Ma che dire di un altro codice che utilizza la tua API? Si romperà perché sta ancora cercando il vecchio nome. Quello che vuoi veramente qui è che puoi cambiare le tue entità e non influenzare l'API pubblica fintanto che tutte le informazioni sono ancora lì. La soluzione: avere classi separate per l'API. Per ogni Entità, hai un'altra classe che (in questo momento) rispecchia l'Entità. Quando si riceve input dall'API, convertire il JSON in queste istanze intermedie. Esegui la convalida e aggiungi dati e solo successivamente alle tue entità. Quando si forniscono dati, convertire prima le entità in quelle classi intermedie e quindi convertirle in JSON. Sì, questo significa più lavoro. Ma ti offre flessibilità che avrà sicuramente bisogno del 100% non appena avrai pubblicato la tua API. Quel lavoro è ora più semplice di 30 funzionalità successive.

imposizione delle autorizzazioni

Ora puoi decidere se includere questa responsabilità nelle classi di rappresentazione dell'API o se la vuoi separatamente. Si potrebbe anche includere questo nel processo di copia dei dati dall'entità alla classe di rappresentazione. Dipende davvero dalla tua base di codice, dalla squadra e dalle preferenze. Assicurati che, ovunque tu posizioni quel codice, l'SRP non sia violato.

prestazioni

Come è stato detto, puoi arrivare addirittura a non recuperare i campi dal DB che non sono visibili a causa delle autorizzazioni. Per i campi regolari l'impatto sulle prestazioni dovrebbe essere ignorabile (tranne quando si tratta di campi BLOB con diversi KB). Ma dove ciò conta davvero è con le entità correlate. Se riesci a evitare tre join perché non verranno comunque utilizzati, si tratta di un enorme e definitivo aumento di velocità. Vedi la risposta di Iipavlov su questo argomento.

    
risposta data 26.05.2018 - 09:40
fonte
0

Creo un ambito dinamico nel modello ( link ) che ottiene come input il permesso e modifica la query select per restituire solo i campi consentiti per permessi specifici.

    
risposta data 04.06.2016 - 22:03
fonte

Leggi altre domande sui tag