@Stateless

@RolesAllowed({"user", "employee", "admin"})

@RunAs("inventoryDpt")

public class ItemEJB {

··@PersistenceContext(unitName = "chapter08PU")

··private EntityManager em;

··@EJB

··private InventoryEJB inventory;

··public List findBooks() {

····TypedQuery query = em.createNamedQuery("findAllBooks", Book.class);

····return query.getResultList();

··}

··public Book createBook(Book book) {

····em.persist(book);

····inventory.addItem(book);

····returnbook;

··}

}

Как вы можете видеть, декларативная авторизация дает вам легкий доступ к политике аутентификации. Но что, если необходимо предоставить параметры безопасности индивида или применить какую-либо бизнес-логику на основе текущей роли принципала? Здесь вам поможет программная авторизация.

<p>Программная авторизация</p>

Декларативная авторизация охватывает большинство вопросов безопасности, которые необходимо решить приложению. Но иногда нужно настроить более тонкую авторизацию (позволив запустить блок кода, а не целый метод, разрешить или запретить доступ к индивиду вместо роли и т. д.). Вы можете использовать программную авторизацию, чтобы выборочно разрешать или блокировать доступ к роли или принципалу. Это становится возможно потому, что у вас есть прямой доступ к интерфейсу JAAS java.security.Principal, а также к контексту EJB, что позволяет проверить роль принципала в коде.

Интерфейс SessionContext определяет следующие методы, связанные с безопасностью:

• isCallerInRole() — возвращает переменную типа boolean и проверяет, имеет ли вызывающая сторона заданную роль безопасности;

• getCallerPrincipal() — возвращает java.security.Principal, который идентифицирует вызывающую сторону.

Чтобы понять, как применять эти методы, рассмотрим пример. Класс ItemEJB в листинге 8.9 не использует декларативные методы безопасности, но нуждается в выполнении какой-то проверки программно. Прежде всего, компоненту необходимо получить ссылку на его контекст (с помощью аннотации @Resource). В связи с этим метод deleteBook() может проверить, имеет ли вызывающая сторона роль admin. Если результат проверки отрицательный, генерируется исключение java.lang.SecurityException, уведомляющее пользователя о нарушении авторизации. Метод createBook() выполняет бизнес-логику с использованием ролей и принципалов. Обратите внимание, что метод getCallerPrincipal() возвращает объект типа Principal, который имеет имя. Метод проверяет, соответствует ли имя принципала значению "paul", а затем устанавливает значение "special user" в сущности книги.

Листинг 8.9. Компонент, использующий программную безопасность

@Stateless

public class ItemEJB {

··@PersistenceContext(unitName = "chapter08PU")

··private EntityManager em;

··@Resource

··private SessionContext ctx;

··public void deleteBook(Book book) {

····if (!ctx.isCallerInRole("admin"))

······throw new SecurityException("Разрешено только администраторам");

····em.remove(em.merge(book));

··}

··public Book createBook(Book book) {

····if (ctx.isCallerInRole("employee") &&!ctx.isCallerInRole("admin")) {

······book.setCreatedBy("employee only");

····} else if (ctx.getCallerPrincipal(). getName(). equals("paul")) {

······book.setCreatedBy("special user");

····}

····em.persist(book);

····returnbook;

··}

}

<p>Все вместе</p>

В разделе «Все вместе» главы 4 я продемонстрировал разработку сущности Book (показанную в листинге 4.3), которая отображается в базе данных Derby. Тогда я показал вам класс Main (см. листинг 4.4), который использует менеджер сущностей для сохранения книги и получения всех книг из базы данных (применяя явное разграничение транзакции: tx.begin() и tx.commit()).

Перейти на страницу:

Похожие книги