Содержание


Обеспечение безопасности Java-приложений с помощью Acegi

Часть 5. Защита JavaBeans в приложениях JSF

Настраиваемая безопасность для bean-компонентов, используемых в приложениях JSF

Comments

Серия контента:

Этот контент является частью # из серии # статей: Обеспечение безопасности Java-приложений с помощью Acegi

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Обеспечение безопасности Java-приложений с помощью Acegi

Следите за выходом новых статей этой серии.

Эта серия из пяти статей знакомит с системой безопасности Acegi и показывает, как использовать Acegi для обеспечения безопасности корпоративных Java-приложений. Эта заключительная статья продолжает обсуждение использования Acegi для обеспечения безопасности приложений JSF. В части 4 я показал, как можно обеспечить безопасность страницы JavaServer Faces (JSF) с использованием Acegi без написания какого-либо программного кода на Java. Я также подробно разобрал события, которые происходят при развертывании приложения JSF-Acegi и при обращении пользователя к нему. В этот раз я сосредоточусь на методах обеспечения безопасности JavaBeans в приложениях JSF.

Сначала я покажу, что концепции безопасности bean-компонентов, которые я описывал в части 3 этой серии, могут применяться и к приложениям JSF, но не идеальны для них. Затем я продемонстрирую пару новых методов, особенно удобных для обеспечения безопасности JavaBeans, используемых в приложениях JSF. Я закончу обсуждение представлением четырехступенчатой стратегии, которая позволяет использовать Acegi для обеспечения безопасности bean-компонентов в приложениях JSF без написания какой-либо защитной программы на Java.

Простой метод

Самый простой способ использования защищенных bean-компонентов в JSF-приложении состоит в том, чтобы следовать тому же пятиступенчатому подходу, что использовался в листинге 4 части 3. Там я извлекаю объект контекста Web-приложения среды Spring из контекста сервлета. Позже контекст Web-приложения может быть использован для защищенного доступа к bean-компонентам. В листинге 1демонстрируется использование контекста Web-приложения в странице JSF:

Листинг 1. Получение контекста Web-приложения из контекста сервлета и использование его в странице JSF
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@page import="sample.CatalogBean"%>
<%@page import="org.springframework.web.context.support.WebApplicationContextUtils" %>
<%@page import="org.springframework.web.context.WebApplicationContext" %>

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<html>
<head>
<title>Acegi simple method security application: TEST PAGE</title>
</head>
<body>

   <f:view>
      <h2>
      <h:outputText value="Protected Resource 1:"/>
      </h2>
      <%
      try {
          WebApplicationContext webApplicationContext =
             WebApplicationContextUtils.getWebApplicationContext(
                 this.getServletConfig().getServletContext());
          CatalogBean privateCatalog = (CatalogBean)
             webApplicationContext.getBean("privateCatalog");
          String privateData = catalog.getData();
          request.setAttribute("privateData", privateData);
    }
    catch (Exception e) { }
    %>

    <h3>
    <h:outputText value="#{privateData}"/>
    </h3>

  </f:view>
</body>
</html>

Видно, что в листинге 1 используется класс WebApplicationContextUtils для извлечения экземпляра контекста Web-приложения. WebApplicationContextUtils является служебным классом, предоставляемым Spring.

После получения контекста Web-приложения можно вызвать его метод getBean() для получения ссылки на любой bean-компонент, настроенный в конфигурационном файле Acegi. Затем можно вызвать методы-получатели bean-компонента и сохранить данные, возвращенные этими методами, в качестве параметра в объекте запроса сервлета. Эти шаги позволяют тегу <outputText> из листинга 1 предоставить данные пользователю.

Не лучший способ

Непосредственная работа с данными bean-компонента, как это показывается в листинге 1, делается просто, но не рекомендуется. Такой подход нарушает логику «модель-представление-контроллер» (Model-View-Controller, MVC) в JSF (см. Ресурсы), которая требует использовать для хранения данных приложения bean-компоненты модели. Лучше не применять эту стратегию в приложениях JSF, за исключением, может быть, очень простых случаев.

JSF предоставляет всеобъемлющую функциональность для управления bean-компонентами модели в приложении. Такие bean-компоненты — называемые управляемыми bean-компонентами — используются в большинстве JSF-приложений, поэтому в этих приложениях необходимо обеспечить защиту управляемых bean-компонентов.

Далее в этой статье обсуждаются два типа стратегий использования защищенных bean-компонентов в приложениях JSF:

Защита управляемых bean-компонентов JSF

Посмотрите на JSF-страницу, показанную в листинге 2, в которой используется управляемый bean-компонент JSF catalog:

Листинг 2. Простая JSF-страница, в которой используется управляемый bean-компонент
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<html>
<head>
<title>JSF Acegi simple method security application: TEST PAGE</title>
</head>

<body>
   <f:view>
      <h2>
      <h:outputText value="Protected Resource 1:"/>
      </h2>
      </br>
      <h3>
      <h:outputText value="#{catalog.publicData}"/>
      </br>
      <h:outputText value="#{catalog.privateData}"/>
      </h3>
   </f:view>
</body>
</html>

В листинге 2 используется два тега JSF <outputText>. В первом теге <outputText> есть атрибут value со значением #{catalog.publicData}, а во втором — атрибут value со значением #{catalog.privateData}. Эти два тега используют свойства publicData и privateData bean-компонента catalog, которые предоставляют соответственно открытые и закрытые данные каталога.

Вспомните, как в разделе "Доступ через созданные прокси к Java-объектам" части 3 я конфигурировал два bean-компонента Acegi: publicCatalog и privateCatalog. Теперь я собираюсь отобразить bean-компонент publicCatalog из части 3 (незащищенный bean-компонент, предназначенный для открытого доступа) на свойство publicData bean-компонента catalog. Аналогичным образом я собираюсь отобразить privateCatalog из части 3 (защищенный bean-компонент с прокси, сконфигурированный в листинге 3 в части 3) на свойство privateData управляемого bean-компонента catalog из листинга 2, приведенного выше. Правильно отображенный bean-компонент catalog ведет себя просто как обертка для открытых и закрытых данных JSF-приложения catalog.

Определение управляемого bean-компонента

В листинге 3 показывается, как определить bean-компонент catalog, чтобы его свойства publicData и privateData отображались соответственно на bean-компоненты Acegi publicCatalog и privateCatalog:

Листинг 3. Отображение свойств catalog на bean-компоненты Acegi
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

  <managed-bean>
     <managed-bean-name>catalog</managed-bean-name>
     <managed-bean-class>sample.Catalog</managed-bean-class>
     <managed-bean-scope>request</managed-bean-scope>

     <managed-property>
        <property-name>publicData</property-name>
        <value>#{publicCatalog.data}</value>
     </managed-property>

     <managed-property>
        <property-name>privateData</property-name>
        <value>#{privateCatalog.data}</value>
     </managed-property>
  </managed-bean>

  <application>
     <variable-resolver>
        org.springframework.web.jsf.DelegatingVariableResolver
     </variable-resolver>
  </application>

</faces-config>

В листинге 3 фактически приведен конфигурационный файл для JSF. Его корневой тег —<faces-config>знаком большинству JSF-программистов. Корневой тег <faces-config> содержит два дочерних тега с именами <managed-bean> и <application>. Теперь я подробно объясню эти два тега.

Объявление свойств bean-компонента в конфигурационном файле JFS

Тег <managed-bean> в листинге 3 определяет bean-компонент catalog и его свойства. У тега <managed-bean> есть три дочерних тега — <managed-bean-name>, <managed-bean-class> и <managed-bean-scope> — и пара тегов <managed-property>. Первые два дочерних тега определяют соответственно имя bean-компонента (catalog) и класса (sample.Catalog).

Каждый тег <managed-property> в листинге 3 определяет свойство bean-компонента catalog. Каждый тег <managed-property> имеет два дочерних — <property-name> и <value> — которые определяют соответственно имя и значение свойства. Глядя в листинг 3, можно увидеть, что имя первого свойства —publicData, а его значение —#{publicCatalog.data}. Аналогично, имя второго свойства —privateData, а его значение —#{privateCatalog.data}.

Эти два значения фактически являются выражениями, которые сводятся к свойствам другого управляемого bean-компонента. Первое выражение (#{publicCatalog.data}) сводится к свойству data компонента publicCatalog. Аналогично, второе выражение (#{privateCatalog.data}) сводится к свойству data компонента privateCatalog.

JSF предоставляет механизм, который сводит выражения типа #{publicData.data} к экземплярам фактических управляемых bean-компонентов. Обсуждать механизм разрешения выражений в JSF я буду двумя строчками ниже (в разделе "Определение средства для разрешения выражений").

Но тут есть затруднение. В конфигурационном файле JSF в листинге 3 нет управляемых bean-компонентов publicCatalog и privateCatalog. Вспомните, что я конфигурировал IOC bean-компоненты publicCatalog и privateCatalog (а не управляемый bean-компонент JSF) в разделе "Доступ через созданные прокси к Java-объектам" в части 3. Следовательно, механизм разрешения выражений JSF должен быть способен разрешить IOC bean-компоненты Acegi.

Определение средства для разрешения выражений

JSF-класс javax.faces.el.VariableResolver является стандартным средством для разрешения выражений, способным сводить выражения к управляемым bean-компонентам JSF. Однако VariableResolver не может разрешать IOC bean-компоненты.

JSF предоставляет механизм расширяемости, дающий разработчикам возможность писать свои собственные средства разрешения выражений. Spring предоставляет средство разрешения выражений для JSF в классе org.springframework.web.jsf.DelegatingVariableResolver. Класс DelegatingVariableResolver может делать разрешение выражений в IOC bean-компоненты. DelegatingVariableResolver также использует стандартный VariableResolver для разрешения выражений в управляемые bean-компоненты JSF.

Чтобы использовать DelegatingVariableResolver, из Spring, необходимо настроить его в конфигурационном файле JSF. Именно для этой цели вставлен тег <application> в листинге 3 (для удобства воспроизведен в листинге 4 ):

Листинг 4. Тег <application>
<faces-config>
   ..........
  <application>
     <variable-resolver>
        org.springframework.web.jsf.DelegatingVariableResolver
     </variable-resolver>
  </application>

</faces-config>

Тег <application> в листинге 4 содержит только один дочерний тег <variable-resolver>, который предназначен для конфигурирования внешних средств разрешения для JSF-приложения. Тег <variable-resolver> обертывает имя класса для разрешения выражений в Spring (org.springframework.web.jsf.DelegatingVariableResolver), который обслуживает разрешение выражений в IOC bean-компоненты.

Реализация JSF и IOC bean-компонентов

Ранее было показано, как конфигурировать JSF-приложение для использования IOC bean-компонентов Acegi. Теперь можно взглянуть на эти три bean-компонента, которые мы только что сконфигурировали.

В листинге 5 показывается реализация класса Catalog, экземпляр которого, названный catalog , сконфигурирован в JSF как управляемый bean-компонент:

Листинг 5. Класс Catalog class
package sample;

public class Catalog
{
   private String publicData = null;
   private String privateData = null;

   public Catalog () {
   }

   public void setPublicData(String publicData)  {
      this.publicData = publicData;
   }

   public void setPrivateData(String privateData)  {
      this.privateData = privateData;
   }

   public String getPublicData() {
      return publicData;
   }

   public String getPrivateData() {
      return privateData;
   }
}//Catalog

Из листинга 5 видно, что класс Catalog просто содержит getter- и setter-методы для своих свойств publicData и privateData. Среда JSF будет вызывать эти методы получения и записи свойств, об этом я расскажу в следующем разделе.

Теперь взглянем на реализацию двух IOC bean-компонентов (publicCatalog и privateCatalog) в листинге 6:

Листинг 6. IOC bean-компоненты publicCatalog и privateCatalog
//PublicCatalog
package sample;

public class PublicCatalog implements CatalogBean {

   public PublicCatalog () {  }

   public String getData()  {
         return "This is public catalog data";
   }
}

//PrivateCatalog
package sample;

public class PrivateCatalog implements CatalogBean {

    public PrivateCatalog () {    }

    public String getData()  {
       return "This is private catalog data";
    }
}

В листинге 6 можно видеть, что я жестко запрограммировал фактические открытые и закрытые данные в этих двух IOC bean-компонентах. В реальном приложении эти bean-компоненты считывали бы данные из базы данных.

Итак, мы показали все компоненты и конфигурации, необходимые для обеспечения безопасности данных, заключенных в управляемых bean-компонентах JSF. Теперь настало время увидеть, как JSF и Acegi работают вместе, используя компоненты и конфигурации.

Совместная работа JSF и Acegi по обеспечению безопасности управляемых bean-компонентов

Последовательность событий, показанная на рис. 1 имеет место, когда пользователь пытается обратиться к JSF-странице из листинга 2. Я включил все события, которые задействуют URL-безопасность Acegi, а также безопасность bean-компонентов в JSF-приложениях.

Рис. 1. Совместная работа компонентов JSF и Acegi
Совместная работа компонентов JSF и Acegi
Совместная работа компонентов JSF и Acegi

События на рис. 1 происходят в такой последовательности:

  1. Пользователь обращается к JSF-странице.
  2. Acegi проверяет, разрешен ли этому пользователю доступ к JSF-странице. (См. раздел "Обработка запроса JSF-страницы, защищенной Acegi" в части 4.
  3. Если процесс авторизации завершается успешно, управление передается сервлету JSF, который подготавливается предоставить JSF-страницу.
  4. Во время подготовки JSF находит bean-компонент catalog в JSF-странице, показанной в листинге 2.
  5. JSF ищет в конфигурационном файле, приведенном в листинге 3, определение bean-компонента catalog и создает его экземпляр. JSF также проверяет свойства bean-компонента catalog в конфигурационном файле. Он находит, что свойства bean-компонента catalog bean's publicData и privateData отображаются на bean-компоненты publicCatalog и privateCatalog, которые не сконфигурированы как управляемые bean-компоненты JSF в листинге 3.
  6. JSF использует средство разрешения переменных Spring DelegatingVariableResolver (сконфигурировано в листинге 4) для разрешения bean-компонентов publicCatalog и privateCatalog.
  7. JSF использует Acegi для вызова методов-получателей bean-компонентов publicCatalog и privateCatalog для извлечения открытых и закрытых данных.
  8. Acegi опять выполняет процесс авторизации для доступа к bean-компонентам. (См. в части 3 подробное обсуждение этого процесса авторизации для Java-объектов.)
  9. 1.Если Acegi находит, что пользователь имеет доступ к bean-компонентам, он вызывает методы получения, извлекает открытые и закрытые данные и предоставляет данные JSF.
  10. JSF вызывает методы записи bean-компонента catalog для записи открытых и закрытых данных в bean-компонент catalog.
  11. JSF выполняет свой жизненный цикл и выдает JSF-страницу.

Пример приложения JSF-Acegi с защищенными управляемыми bean-компонентами

К этой статье прилагается пример приложения JSFAcegiSampleWithSecureManagedBeans (см. Загрузки). В нем методы, о которых говорилось в предыдущих разделах, используются для обеспечения безопасного доступа к данным, содержащимся в управляемых bean-компонентах JSF.

Развертывание примера приложения делается в соответствии с двумя шагами в разделе "Установка и запуск приложения" в части 1. Необходимо также загрузить и распаковать файл jsf-1_1_01.zip с сайта Sun по JSF (см. Ресурсы). Скопируйте все файлы из jsf-1.1.X.zip в папку WEB-INF/lib приложения JSFAcegiSampleWithSecureManagedBeans. Потребуется также загрузить файл cglib-full-2.0.2.jar (который использовался в части 3 этой серии статей) и скопировать его в папку WEB-INF/lib приложения JSFAcegiSampleWithSecureManagedBeans. Чтобы запустить пример приложения, откройте в браузере страницу http://localhost:8080/JSFAcegiSampleWithSecureManagedBeans.

Непосредственное использование IOC bean-компонентов Acegi в JSF-приложении

Мы рассказали, как отображать свойства управляемых bean-компонентов JSF на IOC bean-компоненты Acegi и как сконфигурировать DelegatingVariableResolver для разрешения выражений в IOC bean-компоненты. Также было показано, как осуществляется совместная работа JSF и Acegi для обеспечения безопасного доступа к данным bean-компонента.

Как вариант можно использовать IOC bean-компоненты непосредственно в JSF-страницах, как показано на странице JSF в листинге 7:

Листинг 7. Использование IOC bean-компонентов непосредственно в JSF-странице
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<html>
<head>
<title>JSF Acegi simple method security application: TEST PAGE</title>
</head>

<body>
   <f:view>
      <h2>
      <h:outputText value="Protected Resource 1:"/>
      </h2>
      </br>
      <h3>
      <h:outputText value="#{publicCatalog.data}"/>
      </br>
      <h:outputText value="#{privateCatalog.data}"/>
      </h3>
   </f:view>
</body>
</html>

Содержание листинга 7 аналогично JSF-странице из листинга 2. Единственное отличие между ними заключается в атрибутах value тегов <outputText>. В листинге 2 атрибуты value ссылаются на catalog, который является управляемым bean-компонентом JSF. В листинге 7 атрибуты value ссылаются непосредственно на IOC bean-компоненты (то есть, publicCatalog и privateCatalog). Это означает, что когда пользователь обращается к JSF-странице в листинге 7, JSF прямо распознает Acegi IOC с помощью Spring DelegatingVariableResolver.

Обратите внимание, что при разрешении IOC bean-компонентов, используемых в JSF-странице, DelegatingVariableResolver работает так же, как я объяснял при обсуждении рис. 1.

На рис. 2 представлена последовательность событий, происходящих, когда пользователь обращается к JSF-странице из листинга 7.

Рис. 2. Компоненты JSF и Acegi обслуживают JSF-страницу с защищенными IOC bean-компонентами
Компоненты JSF и Acegi обслуживают JSF-страницу с защищенными IOC bean-компонентамиа
Компоненты JSF и Acegi обслуживают JSF-страницу с защищенными IOC bean-компонентамиа

Последовательность событий, приведенная на рис. 2, лишь незначительно отличается от последовательности на рис. 1:

  1. Пользователь обращается к JSF-странице.
  2. Acegi проверяет, имеет ли пользователь право на доступ к JSF-странице.
  3. Если процесс авторизации завершается успешно, управление передается JSF, который готовится обслужить JSF-страницу.
  4. Во время подготовки, JSF ищет bean-компоненты publicCatalog и privateCatalog в JSF-странице в листинге 7.
  5. JSF проверяет конфигурационный файл из листинга 3 и находит, что bean-компоненты publicCatalog и privateCatalog не сконфигурированы как управляемые bean-компоненты JSF в конфигурационном файле. JSF использует Spring DelegatingVariableResolver для разрешения bean-компонентов publicCatalog и privateCatalog.
  6. JSF использует Acegi для вызова методов-получателей bean-компонентов publicCatalog и privateCatalog для извлечения открытых и закрытых данных.
  7. Acegi выполняет процесс авторизации для доступа к bean-компонентам.
  8. Если Acegi находит, что пользователь авторизован для доступа к bean-компонентам, он вызывает методы получения, извлекает открытые и закрытые данные и предоставляет данные JSF.
  9. JSF выполняет свой жизненный цикл и выдает JSF-страницу.

В JSF-странице из листинга 7 не используются управляемые bean-компоненты, поэтому на рис. 2 нет событий, относящихся к управляемым bean-компонентам JSF.

Второй пример приложения, названный JSFAcegiSampleWithIOCBeans, находится в исходном тексте этой статьи (см. Загрузки). В JSFAcegiSampleWithIOCBeans используется JSF-страница из листинга 7 для демонстрации применения IOC bean-компонентов в JSF-страницах.

Применение Acegi для обеспечения безопасности существующих JSF-приложений

В предыдущем разделе было показано, что можно непосредственно использовать IOC bean-компоненты в JSF-приложениях. Если уже есть JSF-приложение и нужно использовать Acegi для его защиты, необходимо просто выполнить четыре конфигурационных шага:

  1. Написать конфигурационный файл Acegi, как описывалось в первых трех статьях этой серии.
  2. Написать файл web.xml, как описывалось в части 4.
  3. Использовать Spring DelegatingVariableResolver в конфигурационном файле JSF, как описывается в этой статье в разделе "Определение средства разрешения выражений".
  4. Переконфигурировать те управляемые bean-компоненты JSF, которые нужно защитить как IOC bean-компоненты, путем объявления этих bean-компонентов в конфигурационном файле Acegi, а не в конфигурационном файле JSF.

Этот метод дает возможность разрабатывать JSF-приложения без учета вопросов, связанных с безопасностью. После разработки приложения можно в соответствии с этими четырьмя шагами конфигурирования развернуть Acegi без написания программы защиты на Java.

Заключение

В этой серии статей мы рассказали, как использовать Acegi для обеспечения безопасности Java-приложений. Теперь читатели знают, как усилить безопасность как на основе URL, так и на основе методов, а также как спроектировать политику управления доступом и сохранить ее в сервере каталогов, как настроить взаимодействие Acegi с сервером каталогов и как принимать решения по аутентификации и авторизации на основе хранящейся в каталоге политики доступа. В этой и предыдущей статьях мы сфокусировали внимание на JSF-приложениях и узнали, как можно обеспечить безопасность JSF-приложений без написания программ безопасности на Java.


Ресурсы для скачивания


Похожие темы


Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=501542
ArticleTitle=Обеспечение безопасности Java-приложений с помощью Acegi: Часть 5. Защита JavaBeans в приложениях JSF
publish-date=07212010