2012-05-28 3 views
4

В приложении JPA У меня есть сценарий, в котором приложение является дляJava - эффективная авторизация на уровне экземпляра на базе базы данных?

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

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

Теперь я планировал добавить явный слой авторизации (на основе Apache Shiro/пружинную безопасности/другой), чтобы изолировать авторизации, связанные с логикой от остальной части коды, но ...

Есть некоторые 10k Учетные записи в базе данных, а «средний» пользователь получает «депозит» на всех из них, «просмотр» на одну половину и «нахождение» всего лишь на несколько.

Является ли какая-либо система безопасности эффективной для реализации этого сценария?

Т.е.: любой из них может «украсить» запрос JPA типа «выберите a из учетной записи a» (или эквивалентный SQL) и, таким образом, получить список учетных записей без загрузки всех пользовательских грантов из базы данных и все средства, без получения всех счетов?)

+0

... и вы не имеете объект пользователя, который связан с полномочиями и может просто «SELECT * FROM Account WHERE Account.userAuths.user = пользователь "? –

+0

Yep - вот что делает приложение прямо сейчас. Мне интересно, разрешает ли какая-либо инфраструктура auth удалить связанное с авторизацией соединение из кода. – giorgiga

+0

Может ли запрос NamedNativeQuery возвращать объекты учетной записи, такие как 'select acc. * Из учетной записи acc, user_auth uauth, где uauth.user_id =: login_userid' help? –

ответ

3

Посмотрите Apache Shiro.

Он позволяет выполнить авторизацию пользователя один раз и кешировать его на время сеанса. Кроме того, если все пользователи могут ПРОСМОТРЕТЬ все АККАУНТЫ, вам не нужно явно определять это, что значительно снизит накладные расходы.

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

Shiro позволяет реализовать типичный RBAC и определить права доступа, как это:

domain:action:instance 

Так что в ваших разрешениях случае может выглядеть следующим образом для пользователя:

account:deposit:* // deposit all accounts 
account:view:1111 
account:view:2222 
account:view:3333 // view on these accounts 
account:withdraw:5555 
account:withdraw:6666 // withdraw on these accounts 

В коде вы можете затем что-то вроде этого:

if (SecurityUtils.getSubject().isPermitted("account:withdraw:"+account.getAccountNumber()) { 
    // handle withdraw 
} 

У Shiro также есть разрешение на ведение аннотации с для дополнительной абстракции.

EDIT

права доступа Shiro является конечным результатом, не там, где вы начинаете. Я использовал набор таблиц, представляющих сопоставления от пользователя к роли и роли для разрешения вместе с другими сопоставлениями для экземпляра. После AuthN обычно представляет собой простой набор запросов, проиндексированных пользовательской PK для создания структур данных, необходимых для предоставления разрешений.

+0

Когда у вас есть разрешение «account: view: 1111,2222,3333 и т. Д., Как вы создаете запрос на создание запроса к базе данных? Разбираем часть уровня экземпляра разрешения? Представьте, что у вас есть тысячи идентификаторов в разрешении просмотра Это не кажется очень эффективным. – singe3

0

у меня есть надежда, что это одна из возможностей для реализации ваших требований с Spring-Security.

  1. Написать обычай org.springframework.security.acls.Permission как ViewAccount, DepositToAccount, WithDrawFromAccount

  2. Написать пользовательские org.springframework.security.access.PermissionEvaluator Override hasPermission(Authentication userAuthentication,Object accountObject,Object oneOfThePermission), чтобы проверить, если пользователь имеет определенное разрешение на accountObject

  3. Получить ссылку на JPA EntityManager в вас г пользовательских оценщик и перепроверить/проверить в БД с user_id, permission_id, account_ID

  4. Если пользователь «корень» вы можете Staight прочь вернуться верно для hasPermission без проверки с БД.

  5. аннотировать сервис звонков с @PreAuthorize("isAuthenticated() and hasPermission(#accountArgument, 'respectivePermission')")

link см для пользовательских реализаций PermissionPermissionEvaluator &

+0

похоже, что hasPermission необходимо вызывать на экземпляре _each_ Account ... Я боюсь, что он не сможет работать без извлечения всех строк из базы данных (то есть: загрузка объектов 10k только для отображения нескольких) – giorgiga

+0

См. эти ссылки http: // stackoverflow .com/questions/559480/how-to-limit-user-access-at-database-level-in-hibernate, http://jpasecurity.sourceforge.net/ –

+0

Эта вещь JPASecurity кажется очень альфа, но также является только применимый lib Я смог найти ... @Ahamed, если вы отредактируйте свой ответ, сделав его ссылкой на jpasecurity (комментарии будут также оценены потенциальными читателями). Я соглашусь с этим. – giorgiga

0

Если вы используете EclipseLink есть несколько особенностей, для этого,

один является аннотацией @AdditionalCriteria которые позволяют фильтр быть применен ко всем запросам для класса,

http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_additionalcriteria.htm#additionalcriteria

другая поддержка EclipseLink для Oracle ДДП (строка безопасности уровня в базе данных),

http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing

и, наконец, EclipseLink поддерживает SessionEvents, которые могут позволить фильтру быть добавлен к любому выполнения запроса,

http://www.eclipse.org/eclipselink/api/2.4/org/eclipse/persistence/sessions/SessionEventAdapter.html#preExecuteQuery%28org.eclipse.persistence.sessions.SessionEvent%29

Смежные вопросы