Come impedisco agli utenti di modificare le risorse che non possiedono?

10

Sto scrivendo un server in cui ho un'entità StoreOwner che "possiede" o ha una relazione @OneToMany con un'entità Store (un proprietario di un negozio ha da 1 a N negozi). Ogni Store ha Offer e Item , ognuno ha anche una relazione @OneToMany con il negozio (un negozio ha offerte da 1 a N e articoli da 1 a N).

Sto già utilizzando GWT Xsrf protection e un ID di sessione che viene associato all'utente loggato dopo ogni log-in (cookie).

Manca una cosa IMHO: cosa succede se un utente che ha effettuato l'accesso invia una richiesta di eliminazione al server con ID di elementi che non possiede di un negozio che non possiede? Al momento, lo sto facendo nel mio StoreService :

// StoreService.java

@Transactional
public ItemDTO deleteItem(String sessionId, Long storeId, ItemDTO itemDto) {

    // sessionId is the cookie I have placed in my database
    // This way I want to ensure that I am only accessing a store
    // that is associated with the logged in store owner (the user basically)
    Store store = this.storeOwnerRepository.getStore(sessionId, storeId);

    Item item = ConvertDTO.convertItem(store, itemDto);

    // Check if the store ID that I got using the cookie is the
    // same ID as the store ID from the item that should be deleted
    if(item .getStore().getId() == store.getId()) {
        item = this.storeOwnerRepository.deleteItem(item);
    } else {
        // If this didn't work we have a potentially hostile user:
        throw new RuntimeException("Is somebody trying to delete items of a store he doesn't own?");
    }

    itemDto = ConvertEntity.convertItem(item);
    return itemDto;
}

È la prima volta che cerco di scrivere un'applicazione server più grande e voglio impedire agli utenti di fare cose del genere.

La mia domanda è duplice: [1] fa ciò che sto facendo impedirebbe davvero a un utente connesso di contrabbandare gli ID di un altro negozio che non possiede sul mio server? Inoltre, [2] posso semplificarlo un po '?

Il mio problema è che con l'aumentare della domanda si potrebbe - ogni tanto - dimenticare questo controllo

if(item .getStore().getId() == store.getId()) { /* .. */ }

Ovviamente, potrei spostarlo nel mio StoreOwnerRepository , ma ho opzioni migliori?

    
posta displayname 10.09.2015 - 00:46
fonte

1 risposta

12

Questo è chiamato Controllo degli accessi.

Devi verificare che un utente abbia accesso a un record prima di eseguire un'operazione su di esso.

Il metodo più semplice sarebbe utilizzare un database o uno schema diverso per tenant. Oppure ...

Mentre usi Java, potresti usare Spring Security. Ora si integra con Spring Data JPA, consentendo per passare facilmente userid / username nelle tue query SQL.

O usa la sicurezza di riga nel database. Oracle se hai $ 10M da spendere, o questo sarà disponibile per PostgreSQL a ottobre. Puoi imitarli con le viste aggiornabili di security_barrier CHECK OPTION a partire da PG 9.4. Per questo dovresti avere il server web dire al server db il nome dell'utente corrente.

Probabilmente vuoi aggiungere una colonna owner_id alle tue tabelle "figlio". Utilizza una chiave esterna on update cascade nella tabella padre.

    
risposta data 10.09.2015 - 02:00
fonte

Leggi altre domande sui tag