2010-05-21 12 views
5

Ho un POJO in Google Web Toolkit come questo che posso recuperare dal server.Sicurezza durante l'utilizzo di GWT RPC

class Person implements Serializable { 
    String name; 
    Date creationDate; 
} 

Quando il client apporta modifiche, ho salvarlo al server utilizzando il GWT RemoteServiceServlet in questo modo:

rpcService.saveObject(myPerson,...) 

Il problema è che l'utente non dovrebbe essere in grado di cambiare il creationDate. Poiché il metodo RPC è in realtà solo un POST HTTP per il server, è possibile modificare lo creationDate modificando la richiesta POST.

Una soluzione semplice sarebbe quella di creare una serie di funzioni RPC come changeName(String newName), ecc., Ma con una classe con molti campi richiederebbero molti metodi per ogni campo e sarebbe inefficiente cambiare molti campi contemporaneamente.

Mi piace la semplicità di avere un singolo POJO che posso usare sia sul server che sul client GWT, ma ho bisogno di un modo per farlo in modo sicuro. Qualche idea?

EDIT

sto inviare nuovamente con una taglia per provare e vedere se ci sono altre idee. Forse la mia domanda iniziale si concentrava troppo sulle specifiche del GWT. In realtà penso che questa sia una domanda generica per qualsiasi sistema che usi JavaBeans per passare dati tra un ambiente sicuro (servlet container) e un ambiente insicuro (browser web).

EDIT 2

Inoltre, per essere chiari, ho usato il campo creationDate come esempio del problema. In realtà il codice con cui sto lavorando è più complicato con molti campi diversi.

+0

Informazioni su EDIT 2: Non penso che ci sia molta differenza tra il campo creationDate e altri campi - eccetto che il creationDate potrebbe avere alcune complessità aggiuntive tipiche della gestione di data/ora. Le autorizzazioni sono il solito modo di gestire tutti i dati in arrivo e in uscita - per alcuni oggetti/campi, questo è molto facile negando sempre tutti gli aggiornamenti. Per altri oggetti/campi, le autorizzazioni possono essere molto elaborate, basate su verifiche su strutture di dati complesse, valutate individualmente per ciascun utente. In ogni caso, i controlli vengono eseguiti sul server: non eseguirli sul client. –

risposta

3

Ti consiglio di mantenere il tuo singolo metodo RPC e di utilizzare un mappatore POJO/bean come Dozer o Gilead.

  • Con Dozer, si crea un class-mapping utilizzato per copiare le proprietà da un oggetto a un altro. Se non si specifica una proprietà nel mapping di classi, non verrà copiata.
  • Con Gilead, @ReadOnly transport annotation dovrebbe essere sufficiente.

Il beneficio collaterale è che non c'è bisogno di cambiare il vostro livello di accesso ai dati (supponendo ne avete uno). Non importa se usi un ORM o meno, con un database relazionale o meno.

0

Bene ... una soluzione accademica (cioè teoricamente possibile, ma piuttosto poco pratica) potrebbe essere quella di eseguire lo hash dello stato dell'oggetto utilizzando una chiave pubblica pubblica che è la chiave privata sul server. Si potrebbe andare qualcosa come questo:

  1. il server genera coppia di chiavi pubblica-privata
  2. il server invia la chiave pubblica con i dati reali al client
  3. il cliente calcola un hash dell'oggetto completo di stato insieme alla chiave pubblica
  4. il client invia l'oggetto e l'hash al server
  5. server ricalcola l'hash per confermare l'integrità del pacchetto

Supponendo che la coppia di chiavi sia cambiata ad ogni requset e che l'utente non possa interferire con il processo di hashing (che può, ma potrebbe essere abbastanza difficile da renderlo utile in alcuni casi d'uso), il server sarebbe in grado di rilevare eventuali cambiamenti nello stato degli oggetti eseguiti dopo che l'hash è stato calcolato sul client.

Ancora una volta, considera questo nient'altro che un esperimento mentale ... Non ti suggerirei di implementare un simile approccio. In generale, devi essere in grado di garantire che la logica sul client non sia stata manomessa prima di ottenere la protezione dei dati.

+1

Perché qualcuno dovrebbe aggiungere la complessità della crittografia solo per evitare gli aggiornamenti del database in colonne predeterminate? – jweyrich

+0

Come ho già detto, non è una cosa che consiglierei di fare. Ho capito che la domanda era fondamentalmente "come si dovrebbe impedire all'utente di modificare una parte di un valore (nell'ambiente tecnologico dato)". Una soluzione ovvia per me è firmare i dati per garantire che non sia stato manomesso. Forse abbiamo capito la domanda in diversi modi. –

+0

Capisci il problema come "Come evitare la manipolazione del traffico". Se fosse il caso, potrebbe semplicemente usare HTTPS. – jweyrich

3

Se il client non deve essere in grado di modificare la data di creazione e mantenerla attiva, modificare la serializzazione (ad es.l'istruzione SQL UPDATE) per non salvare quel campo specifico. Deve essere impostato solo da INSERT (dove arriverà dal server endpoint RPC o dal server di database se si imposta un valore predefinito automatico).

+2

Esattamente. "Non fidarti mai del cliente". Se si dispone di informazioni che l'utente non dovrebbe essere in grado di modificare, non fidarsi dei dati provenienti dal client. Se non si salvano i dati nell'archiviazione permanente fino a quando l'utente non ha la possibilità di modificarli, serializzarli in anticipo e conservare una copia temporanea per estrarre i dati che non dovrebbero essere stati modificati. –

1

userei un approccio basato sui permessi:

  • assegnare ruoli agli utenti (ad esempio utente admin, utenti registrati, utenti ospiti, ...), e
  • associato quei ruoli con autorizzazioni (ad esempio può leggere il nome della persona, può modificare il nome della persona - forse ulteriormente limitando ciò a determinate persone ecc.)

Su ogni richiesta dal client, eseguire un controllo sul server, se l'utente è autorizzato a eseguire quell'azione. Nel caso di "date di creazione", questo probabilmente non è mai permesso a nessuno. Così

  • se la richiesta contiene una data di creazione, è possibile visualizzare un messaggio di errore o di ignorare la richiesta ...
  • se la richiesta non contiene una data di creazione (caso normale), si crea la data sul server - o se la persona ha già una data di creazione, riutilizzala.

Il client di solito specifica la persona tramite un qualche tipo di ID (può essere nullo per una persona appena creata), che il server può utilizzare per cercare persone esistenti. La manomissione dell'ID non dovrebbe avere importanza, in quanto l'utente può comunque modificare solo i dati specificati dalle sue autorizzazioni.

Caso particolare:

Se effettivamente necessario utilizzare una data di creazione fornito al cliente, perché si vuole conoscere un po 'di più esattamente quando l'utente ha fatto clic, l'unica cosa che puoi fare è per verificare che la data di creazione fornita sia compresa tra la richiesta precedente e la richiesta corrente. Tuttavia, dovresti prendere in considerazione la differenza di clock tra il server e il client. E non puoi garantire la precisione.

+0

Questa risposta riguarda principalmente la parte generica alla fine della domanda. Con GWTRPC - se si desidera inviare l'intero oggetto Persona - è possibile consentire che contenga una data di creazione, ma a) ignorarlo, oppure b) verificare che corrisponda a quello sul server. –

1

Perché non rendere privati ​​i campi e fornire solo getCreationDate() e no setCreationDate()?

1

Si potrebbe semplicemente ignorare i valori per i campi immutabili.
Se ciò non è possibile a causa del modo in cui il meccanismo di persistenza è configurato sul server, quando la richiesta arriva al server, recupera un'altra istanza del POJO dall'archivio permanente e popola i campi che sono immutabili con quelli che hai appena avuto.In questo modo qualcuno ha manomesso alcuni campi che non ti interessano.

Naturalmente la crittografia potrebbe essere una soluzione anche per aiutare a evitare manomissioni.

1

Dividi i tuoi oggetti in due parti. Uno contiene solo i campi che il cliente può modificare. Invia entrambi gli oggetti al client, ma salva solo l'oggetto modificabile quando il client lo restituisce. Puoi usare l'ereditarietà qui per rendere la tua vita più semplice.

Se lo strumento di mappatura non si piega come desiderato, implementare un metodo copy() che copia tutti i campi da un oggetto a un altro. Quindi puoi caricare una nuova istanza dell'oggetto dal tuo database, copiare i campi modificabili e poi salvare l'oggetto modificato.

Problemi correlati