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