Маскировка определенных столбцов на основе ролей JHipster

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

Похоже, единственный вариант сделать это — использовать EntityListeners. Я могу использовать EntityListener и замаскировать определенный столбец во время события PostLoad. Скажем, например, я маскирую столбец my_secure_column с помощью XXX и показываю пользователю.

Затем пользователь изменяет некоторые другие поля/столбцы (к которым у него есть доступ) и отправляет форму. Должен ли я снова перехватывать частично заполненный объект в событии PreUpdate, получать исходное значение для my_secure_column из базы данных и устанавливать его перед сохранением?

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

Редактировать 1: это похоже на первый шаг к тому, чтобы достичь этого чуть лучшим способом. Обновление объектов с помощью запроса на обновление в Spring Data JPA

Я мог бы использовать определенные частичные обновления, такие как updateAsUserRole, updateAsManagerRole и т. д., вместо постоянного сохранения всего объекта.

@Repository
public interface CompanyRepository extends JpaRepository<Company, Integer> {
   @Modifying(clearAutomatically = true)
   @Query("UPDATE Company c SET c.address = :address WHERE c.id = :companyId")
   int updateAddress(@Param("companyId") int companyId, @Param("address") String address);
}

person user1880957    schedule 06.01.2017    source источник


Ответы (1)


Безопасность на основе столбцов — непростая проблема, особенно в сочетании с JPA.

В идеале желательно даже не загружать столбцы, но, поскольку вы выбираете сущности, это невозможно по умолчанию, поэтому вам необходимо удалить ограниченное содержимое, переопределив значение после загрузки.

В качестве альтернативы вы можете создать компонент представления (POJO), а затем использовать Выражение конструктора JPQL. Лично я бы использовал CriteriaBuilder. build() вместо объединения запросов JPQL, но по тому же принципу.

Что касается обновления данных, пользовательский интерфейс не должен разрешать редактирование полей с ограниченным доступом. Однако вам все равно нужно выполнить проверку на бэкэнде, и я бы порекомендовал вам проверить, был ли изменен столбец перед вызовом JPA. Обычно у вас есть изменения в DTO, и вам все равно нужно будет загрузить Entity, если был изменен ограниченный столбец, вы бы отправили ошибку обратно. Таким образом, вы вызываете JPA только после проверки безопасности.

person Klaus Groenbaek    schedule 06.01.2017
comment
В JHipster, как правило, при обновлении данные напрямую привязываются к объекту (нет необходимости в отдельном DTO). Итак, в обычном случае мы не загружаем Entity. Это просто обновление/сохранение связанного объекта, полученного из браузера. Но для этого конкретного варианта использования, похоже, нам придется заново загружать сущность, сравнивать и объединять. Это кажется расточительным занятием. - person user1880957; 06.01.2017
comment
Я посмотрел на JHipster, и, хотя он позволяет вам работать, я бы никогда не стал использовать его для производства. Как и в случае с любой генерацией кода, попытка построить универсальный фреймворк всегда будет неудачной (мое мнение за 13 лет). У нас есть младший ресурс, который хотел использовать JHipster, и он дает вам хорошее представление о том, какие компоненты необходимы, но вам следует создать новый проект и обрезать жир. По умолчанию (монолитный) проект JHipster составляет 5000+ строк, как правило, вы нужно 10% от этого, остальное нужно как-то настроить. Сделайте себе одолжение и изучите Spring (ядро, загрузка, безопасность, данные) - person Klaus Groenbaek; 06.01.2017
comment
Я никогда не использовал тот же класс, что и Entity и DTO. Я знаю, что большинство фреймворков JPA предлагают встроенные службы REST для управления данными, но, по моему опыту, это ошибка. Просто существуют разные требования к Entity и DTO, и вам часто требуется уровень безопасности перед обновлением базы данных. Создание в качестве DTO для ваших сущностей — это одноразовая задача, занимающая около 1-5 минут, это ничто по сравнению со временем, которое вы потратите на управление своим классом сущностей, чтобы заставить его делать и то, и другое. Вы можете поверить мне на слово или узнать это сами ;) - person Klaus Groenbaek; 06.01.2017