it-roy-ru.com

Как предотвратить изменения отношений между сущностями?

Я использую Spring Boot для хранения сложных JSON-структур через JPA в нашей базе данных.

Корень json-структуры представляет собой объект «Дом». Объект "Дом" содержит несколько предметов мебели. Например:

House ID: 4711
|- Furniture: ID 4712 (with confidential information)

Пользователи имеют права на чтение/запись для определенных Домов и всех их «Мебели».

Моя проблема в том, что через REST-API пользователь может «украсть» Мебель из других Домов, если он знает их первичные ключи; с такой просьбой:

POST http://localhost:8080/house

{
    houseId: 99991337,
    furnitures: [{
        furnitureId: 4712,
        ...
    }]
}

Это ведет к:

House ID: 4711
|- empty!

House ID: 99991337
|- Furniture 4712 (with confidential information)

Хотя у пользователя не было разрешения на дом 4711, он «связал» Мебель 4712 с домом 4711 и вместо этого связал ее с домом 99991337.

Как я могу запретить смену Дома мебели?

В JPA-Entities существует двунаправленная OneToMany-Relationship от дома до мебели. Я подумал, может быть, поиск в базе данных любой мебели входящих запросов, проверить все разрешения на все из них. Но я бы предпочел только проверить разрешение на дом (потому что в реальной жизни у меня есть гораздо больше объектов, таких как мебель)

13
slartidan

Если мое понимание верно, просто выполните поиск в таблице разрешений по userId и houseId, которые были предоставлены в запросе . Если есть совпадение, то у пользователя есть разрешения на изменение houseId.

В зависимости от разрешений вы можете установить или не устанавливать houseId для объекта, который вы собираетесь сохранить в базе данных.

Если вы все еще хотите, чтобы пользователь изменил furniture data, вы можете сохранить только сущность furniture, указав furnitureId и text для объекта new Furniture().

3
htshame

Прежде всего, ваша структура запроса неверна. В целях безопасности, подобных этой, вы не можете запрашивать у пользователя его ИД пользователя, идентификатор дома и т.д. Вы должны обрабатывать его в фоновом режиме, не полагаясь на запрос пользователя.

Но для этой ситуации вы можете просто изменить оператор вставки с помощью выбора вставки. Присоединитесь к таблице разрешений, чтобы выбрать оператор для проверки того, что данный идентификатор связан с соответствующим пользователем. Если ничего не вставлено, пользователь пытается вставить недопустимый идентификатор.

1
Burak Akyıldız

Если верно следующее утверждение: 

Yes, a furniture should belong to exactly one house and should be privately be owned by that house. Only those users permitted to see/edit the house should be able to see/edit its furniture. 

На мой взгляд, это означает, что вам нельзя разрешать создавать дом с мебелью, которая уже прикреплена к другому дому (бизнес-требования).

Я бы сначала проверил, если мебель не принадлежит другому дому, прежде чем создавать дом (сохранить целостность данных), и выкинул бы исключение, если это так. Я вижу, что это происходит на бизнес-уровне, который будет обслуживать любые внешние вызовы границы, которые могут поставить под угрозу данные/требования.

Вы можете переместить его за пределы своего бизнес-уровня, но тогда есть вероятность, что вы можете дублировать код на канал или пропустить один/два канала.

0
Rentius2407

Я думаю, что вы можете попытаться поместить обработчик в обновление таблицы сущностей Furniture с аннотацией @HandleBeforeSave и @RepositoryEventHandler, а внутри этого обработчика вы можете запросить только эту сущность Furniture и проверить, к какой House она принадлежит. А затем решите, что делать с этим запросом на обновление 

0
vlad324