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

Я использую 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 от дома до мебели. Я подумал, может быть, поиск в базе данных любой мебели входящих запросов, проверить все разрешения на все из них. Но я бы предпочел только проверить разрешение на дом (потому что в реальной жизни у меня есть гораздо больше объектов, таких как мебель)

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

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.

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

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

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