Как ограничить доступ пользователей на уровне базы данных в Hibernate - PullRequest
6 голосов
/ 18 февраля 2009

Приложение

Мне нужно реализовать веб-приложение, которое будет использоваться разными пользователями. Каждый пользователь имеет разные привилегии для разных таблиц, например,

Пользователь A может видеть поля 'name' и 'address' из таблицы Student Пользователь B может видеть поля «имя» и «номер телефона», но не «адрес» из таблицы Student Пользователь C может видеть и изменять все поля, упомянутые выше


У меня будет что-то на уровне пользовательского интерфейса, чтобы ограничить определенный доступ, например, скрыть кнопку «редактировать» для пользователей, у которых нет прав на изменение записей. Тем не менее, я думаю, что у меня должно быть что-то на более низком уровне (возможно, на уровне базы данных) только для обеспечения безопасности данных.


Проблема

Я использую Hibernate, JBoss, DB2 и Struts для своего приложения. Я думаю, что я должен использовать JBoss LoginModule некоторого вида, который аутентифицирует пользователя по базе данных с пользователем / паролем / ролями (но я могу ошибаться (?)). Я провел некоторые исследования и предложил следующие варианты, но ни один из них не подходит для моего случая. Я думаю, что это очень распространенная проблема доступа к данным в многопользовательских веб-приложениях. Может ли кто-нибудь, пожалуйста, указать мне правильное направление? Заранее спасибо!

  1. Используйте тег 'grant' в hibernate.cfg.xml с прослушивателями событий JACC. Это может установить разрешения «вставить», «обновить» и «прочитать» для всех объектов гибернации. Тем не менее, что, если мне нужны более точные элементы управления? Мне нужно установить разрешения на определенные поля, а не весь объект. http://www.hibernate.org/hib_docs/v3/reference/en-US/html/objectstate-decl-security.html

  2. Ограничение разрешений на метод получения / установки каждого ejb. Если я правильно понял, это требует ручной настройки каждого компонента для каждого профиля пользователя, что для меня нереально. Разрешения метода EJB

  3. Код DAO для проверки прав пользователей. Сверните мою собственную служебную функцию, которая проверяет гигантскую таблицу разрешений каждый раз, когда вызывается определенный метод DAO, чтобы определить, может ли вошедший в систему пользователь выполнить действие или нет.

  4. Используйте «перехватчик» и «события» в Hibernate. Определите конкретные события «onLoad», «onSaveorUpdate» и т. Д. Для каждого класса. Могу ли я указать уровень разрешений для отдельных полей в этом случае? http://www.hibernate.org/hib_docs/v3/reference/en-US/html/objectstate-events.html

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


Что такое хороший способ управления доступом к данным здесь

Ответы [ 3 ]

3 голосов
/ 18 февраля 2009
  1. Добавьте ключ безопасности для ваших сущностей, создайте таблицу для разрешений и свяжите пользователя с разрешением с помощью типа сущности, а также с ключом безопасности с ролью. Таким образом, вы можете сказать что-то вроде: Admin_role может получить доступ к Student (тип Entitiy) и читать (Operation in Permission) и Write (Operation), в то время как Student_role может получить доступ к Student_key для себя и Read_permission. Вы можете исправить адрес, реорганизовав его в сущность и добавив к нему ключ безопасности.

    1. Ваш номер четыре может иметь предположение о замкнутом мире и говорить, что, если вы не можете для текущей роли пользователя, связать имя-свойства с флагом в словаре (сущность + свойство) -hash, чтобы пометить закрытый мир предполагает, что чтение не разрешено по умолчанию. Тогда, конечно, вы не получаете никаких разрешений на запись и т. Д.

    2. Вы можете определять представления в своей базе данных и назначать им права, используя систему аутентификации базы данных. Это, вероятно, самый чистый способ, если вы можете сами написать код, способ выбрать, какое представление вызывать, в зависимости от того, какую роль мы выполняем. (Моя бывшая учительница РСУБД хотела бы, чтобы я сказал это;)) Это также немного уходит из Hibernate и больше связывает ваши вещи с базой данных. Я думаю, это зависит от того, насколько мобильным должен быть ваш код.

    3. Используйте аспект вокруг вашего общего дао (IRepository), который переписывает запросы на основе ваших разрешений; это подразумевает, что у вас в коде есть защита на основе разрешений.

Кнопка редактирования, скрывающаяся в графическом интерфейсе, действительно может быть выполнена только в том случае, если вы сначала портируете права доступа к коду, как в моем пункте 1. Я предлагаю вам взглянуть на блог Ayendes , чтобы открыть Источник реализации этого, он очень опытный кодер.

2 голосов
/ 18 февраля 2009

Другим вариантом может быть использование пользовательских типов. Например, вместо сопоставления символа со строкой, сопоставьте его с пользовательским типом, таким как SecureString. Присвойте ему параметр с каким-то уникальным идентификатором в отображении, например, table.column. Затем в методе nullSafeGet пользовательского типа вы можете обратиться к службе безопасности, чтобы узнать, следует ли заполнить значение или просто установить его в значение null. Возможно, вам также придется использовать ThreadLocal для хранения чего-либо, чтобы идентифицировать пользователя или роль. Вам нужно всего лишь создать несколько пользовательских типов, чтобы обернуть строку, двойное число, дату, целое число и т. Д. Я сделал нечто подобное, чтобы разрешить преобразование дат в часовой пояс пользователя.

1 голос
/ 18 февраля 2009

Мне нравится Предложение Хенрика об использовании представлений.

Hibernate фильтры могут работать, но я думаю, что это больше для фильтрации строк, а не столбцов.

Вы также можете использовать [Динамические модели на основе карты] (http://www.hibernate.org/hib_docs/reference/en/html/persistent-classes-dynamicmodels.html) вместе с отдельными [именованными запросами] (http://www.hibernate.org/hib_docs/reference/en/html/querysql-namedqueries.html),) вместо того, чтобы иметь частично заполненные бины. Тогда ваш код представления просто проверяет, содержит ли Map запись для `address` , и показать поле, если найдено?
...