¿Cómo evito que los usuarios modifiquen recursos que no son de su propiedad?

10

Estoy escribiendo un servidor donde tengo una entidad StoreOwner que "posee" o tiene una relación @OneToMany con una entidad Store (el propietario de una tienda tiene 1 a N tiendas). Cada Store tiene Offer y Item , cada uno también tiene una relación @OneToMany con la tienda (una tienda tiene 1 a N ofertas y 1 a N artículos).

Ya estoy usando GWT Xsrf protection y un ID de sesión que se asocia con el usuario que inició sesión después de cada inicio de sesión (cookie).

FALTA una cosa IMPOSITIVO: ¿qué sucede si un usuario que ha iniciado sesión envía una solicitud eliminar al servidor con los ID de los artículos que él no posee de una tienda que él tampoco posee? En este momento, estoy haciendo esto en mi 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;
}

Es la primera vez que intento escribir una aplicación de servidor más grande y quiero evitar que los usuarios hagan esas cosas.

Mi pregunta es doble: [1] ¿lo que estoy haciendo realmente evitaría que un usuario registrado contrabandee las ID de otra tienda que no es de mi servidor? Además, [2] ¿puedo simplificar esto un poco?

Mi problema es que a medida que la aplicación crezca, es posible que, de vez en cuando, olvide esta comprobación

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

Por supuesto, podría mover eso a mi StoreOwnerRepository , pero ¿tengo mejores opciones?

    
pregunta Stefan Falk 10.09.2015 - 00:46
fuente

1 respuesta

12

Esto se llama control de acceso.

Debe verificar que un usuario tenga acceso a un registro antes de realizar una operación en él.

El método más simple sería usar una base de datos o esquema diferente por inquilino. O ...

A medida que usa Java, puede usar Spring Security. Ahora se integra con Spring Data JPA, permitiendo para pasar el ID de usuario / nombre de usuario a sus consultas SQL fácilmente.

O use Row Security en la base de datos. Oracle si tiene $ 10M de sobra, o estará disponible para PostgreSQL en octubre. Puede imitarlo con las opciones actualizadas de security_barrier CHECK OPTION views a partir de PG 9.4. Para esto, tendrías que tener el servidor web dile al servidor db el nombre del usuario actual.

Probablemente desee agregar una columna owner_id a sus tablas "secundarias". Use una clave foránea on update cascade para la tabla principal.

    
respondido por el Neil McGuigan 10.09.2015 - 02:00
fuente

Lea otras preguntas en las etiquetas