Статьи

Безопасная связь SSL EJB с GlassFish


Целью данной статьи является документирование того, как установить безопасную связь SSL между сервером GlassFish EJB и веб-сервером GlassFish, используя сертификаты хранилища ключей со GlassFish 3.0.1.

Начиная с Java Enterprise Edition 5 технология EJB кардинально изменилась. Опираясь на идеи, представленные Spring и другими средами, новые спецификации EJB создали новый простой в использовании стандарт. Приложения могут использовать преимущества корпоративного сервера вместо использования сторонних технологий. Контейнер EJB обеспечивает легкий доступ как к локальным, так и к удаленным компонентам Enterprise Java Beans (EJB). Клиенты, такие как сервлеты, могут использовать внедрение зависимостей для получения экземпляров этих EJB-компонентов без различий в коде с использованием локальных и удаленных компонентов.

Однако использование удаленного Enterprise Java Beans приводит к сетевому трафику между сервером Enterprise, на котором размещены EJB, и клиентским приложением, использующим EJB. С сетевым трафиком возникает вероятность проблем с безопасностью, поэтому цель состоит в том, чтобы обеспечить защиту EJB-связи с помощью SSL.

Эта статья будет шпаргалкой по конфигурации. Шпаргалка предоставит соответствующую информацию, но вы сможете интегрировать ее в свои проекты. Последующие части пройдут через создание и настройку реального рабочего примера.

Шпаргалка

EJB

Создайте интерфейс @Remote для вашего EJB

 Интерфейс @Remote для вас EJB определяет методы, доступные удаленным клиентам, обращающимся к удаленному EJB

    @Remote
public interface AccountService {
public Account findAccount(int id);
}

Создайте @Stateless реализацию интерфейса @Remote для вашего EJB

Реализация может быть @Stateful или @Stateless, но в этом примере создайте реализацию @Stateless удаленного интерфейса.

@Stateless
public class AccountServiceBean implements AccountService
{
@Override
@PermitAll
public Account findAccount(int id)
{
System.out.println(
String.format("ENTER findAccount(%d)",id)
);
Account account = new Account();
account.setAccountId(id);
return account;
}
}

   

 

Создайте файл sun-ejb-jar.xml, который настраивает использование SSL для вашего EJB

Файл sun-ejb-jar.xml — это специальный файл конфигурации GlassFish, отвечающий за настройку EJB. Обычно EJB компилируются в JAR, а затем JAR помещаются в EAR. Файл sun-ejb-jar.xml сохраняется в каталоге META-INF JAR.

Файл sun-ejb-jar.xml должен содержать конфигурацию <ejb> для каждого EJB, который нуждается в безопасном доступе для связи SSL.

За исключением значения <ejb-name>, все остальные значения должны оставаться неизменными. Это была комбинация значений, которые я нашел для правильной работы.

<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//
DTD GlassFish Application Server 3.0 EJB 3.1//EN"
"http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_1-0.dtd">
<sun-ejb-jar>
<enterprise-beans>
<ejb>
<ejb-name>
AccountServiceBean
</ejb-name>
<ior-security-config>
<transport-config>
<integrity>
required
</integrity>
<confidentiality>
required
</confidentiality>
<establish-trust-in-target>
SUPPORTED
</establish-trust-in-target>
<establish-trust-in-client>
REQUIRED
</establish-trust-in-client>
</transport-config>
<sas-context>
<caller-propagation>
supported
</caller-propagation>
</sas-context>
</ior-security-config>
</ejb>
</enterprise-beans>
</sun-ejb-jar>

Создайте файл JAR для вашего EJB

Когда вы создаете файл JAR для вашего EJB, структура каталогов должна быть:

MyBeans.jar
/META-INF
sun-ejb-jar.xml
/com
/mycompany
*.class

WAR

Создайте сервлет для вашей войны

Создайте сервлет, который использует внедрение зависимостей для получения экземпляра EJB. Помните, что с точки зрения сервлета он будет иметь дело только с локальным именем поиска JNDI и интерфейсом @Remote для EJB. Помимо этого, сервлет не знает других подробностей.

Поиск @EJB — это локальное имя поиска JNDI. Это имя существует только в пространстве имен этой WAR. Файлы web.xml и sun-web.xml настраивают, как этот локальный поиск JNDI отображается на реальный экземпляр EJB. Мне нравится использовать локальные имена поиска, потому что, когда WAR настроен правильно и поиск успешен, я уверен, что код нашел правильную вещь. Альтернатива — это магия автоматического поиска, и незнание того, как ресурс найден и введен, не очень хорошая вещь.

  @WebServlet(
name="AccountServlet"
, urlPatterns= {"/account"}
)
public class AccountServlet extends HttpServlet
{
// Remember, this is a
//
// !! LOCAL JNDI LOOKUP NAME !!
//
// and this lookup name is only
// used by this WAR. How this
// local lookup name maps to a
// real EJB instance is configured
// in web.xml and sun-web.xml
@EJB(lookup="java:comp/env/ejb/Sam")
AccountService accountService;
}

Создайте web.xml для вашей WAR

Файл web.xml должен содержать элемент <ejb-ref>. Этот элемент устанавливает 2 значения.

  1. Локальное имя поиска JNDI, которое использует ваш файл WAR при попытке найти EJB
  2. Полное имя интерфейса @Remote EJB.

Вам потребуется элемент <ejb-ref> для каждого локального поиска JNDI, который выполняет WAR.

<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns=
"http://java.sun.com/xml/ns/javaee"
xmlns:web=
"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5"
>
<ejb-ref>
<ejb-ref-name>
ejb/Sam
</ejb-ref-name>
<remote>
org.ferris.ejb.account.AccountService
</remote>
</ejb-ref>
</web-app>

Создайте sun-web.xml для вашей WAR

Файл sun-web.xml — это файл конфигурации GlassFish для вашей WAR. Используйте файл sun-web.xml для сопоставления локального поиска JNDI с WAR с реальным расположением EJB. Наличие кода WAR только о локальном поиске JNDI делает это сопоставление простым, а также позволяет легко изменять конфигурацию между различными средами (при необходимости). 

Некоторые примечания о значении для <jndi-name> ниже:

  1. Он отображается на нескольких строках, но на самом деле все должно быть на одной строке!
  2. Не пропустите ни одного из символов «:», «/» или «!» персонажи
  3. [SERVER_NAME] — это имя сервера GlassFish, на котором развернуты EJB-компоненты @Remote.
  4. [EAR_NAME] — это имя приложения EAR, которое обычно является именем файла EAR. Предположим, вы развернули файл «MyBeans.ear» в GlassFish. По умолчанию GlassFish будет использовать «MyBeans» в качестве имени приложения EAR. Это значение может быть переопределено или изменено, но обычно это имя файла EAR.
  5. [JAR_NAME] — это имя файла JAR внутри файла EAR, в котором содержатся компоненты. Предположим, у вас есть файл «account.jar» внутри файла «MyBeans.ear», который содержит классы EJB для информации об учетной записи. По умолчанию GlassFish будет использовать «account» в качестве имени модуля. Это значение может быть переопределено или изменено, но обычно это имя файла JAR.
  6. [BEAN_NAME] — это, конечно, имя бина. Он должен совпадать с тем, что находится в конфигурационном файле sun-ejb-jar.xml, развернутом с bean-компонентами.
  7. [FULLY_QUALIFIED_REMOTE_INTERFACE] — это значение говорит само за себя. Это полностью квалифицированный интерфейс @Remote EJB.
      <!DOCTYPE
    sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD
    GlassFish Application Server 3.0 Servlet 3.0//EN"
    "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd"
    >
    <sun-web-app>
    <ejb-ref>

    <!--
    | local JNDI lookup name your code uses
    -->
    <ejb-ref-name>ejb/Sam</ejb-ref-name>

    <!--
    | The jndi-name value is the same
    | for both secure and non-secure
    | configuration. The sun-ejb-jar.xml
    | file on the EJB server determines
    | if the two GlassFish instances should
    | establish a secure communications
    -->
    <jndi-name>
    corbaname
    :
    iiop
    :
    [SERVER_NAME]
    :
    3700#java
    :
    global
    /
    [EAR_NAME]
    /
    [JAR_NAME]
    /
    [BEAN_NAME]
    !
    [FULLY_QUALIFIED_REMOTE_INTERFACE]
    </jndi-name>
    </ejb-ref>
    </sun-web-app>

 

Обмен ключами от GlassFish Keystore

Безопасная связь EJB между двумя серверами GlassFish проще всего, когда серверы могут обмениваться сертификатами и автоматически доверять друг другу. Для этого сертификаты в хранилище ключей (keystore.jks) каждого сервера GlassFish необходимо экспортировать, а затем импортировать в хранилище доверенных сертификатов (cacerts.jks) другого сервера GlassFish.

Экспорт сертификата из keystore.jks

Команда для сервера GlassFish EJB

    Выполните следующую команду на сервере GlassFish EJB, чтобы экспортировать сертификат сервера GlassFish EJB.

    C:> cd C: \ glassfish \ 3.1 \ glassfish \ domains \ domain1 \ config
    C:> keytool.exe -export -rfc -alias s1as -keystore keystore.jks -file GlassFishEJBServer.cer

    Пароль по умолчанию для keystore.jks — » Команда changeit

для веб-сервера GlassFish

    Выполните следующую команду на веб-сервере GlassFish, чтобы экспортировать сертификат веб-сервера GlassFish. 

    C:> cd C: \ glassfish \ 3.1 \ glassfish \ domains \ domain1 \ config
    C:> keytool.exe -export -rfc -alias s1as -keystore keystore.jks -file GlassFishWEBServer.cer

    Пароль по умолчанию для keystore.jks — » Измени это» 

Обмен сертификатами

Предположим, вы экспортировали оба сертификата, а имена файлов — GlassFishEJBServer.cer и GlassFishWEBServer.cer. Скопируйте, sftp или используйте любой протокол передачи файлов, который вам нужен для обмена файлами между серверами.

Импортируйте сертификат в cacerts.jks

Команда для сервера GlassFish EJB

    Выполните следующую команду на сервере GlassFish EJB, чтобы импортировать сертификат WEB-сервера GlassFish.

    C:> cd C: \ glassfish \ 3.1 \ glassfish \ domains \ domain1 \ config
    C:> keytool.exe -import -noprompt -trustcacerts -alias glassfishwebserver -file GlassFishWEBServer.cer -keystore cacerts.jks

    Пароль по умолчанию для cacerts.jks is команда «changeit»

для веб-сервера GlassFish

    Выполните следующую команду на веб-сервере GlassFish, чтобы импортировать сертификат сервера GlassFish EJB.

    C:> cd C: \ glassfish \ 3.1 \ glassfish \ domains \ domain1 \ config
    C:> keytool.exe -import -noprompt -trustcacerts -alias glassfishejbserver -file GlassFishEJBServer.cer -keystore cacerts.jks

    Пароль по умолчанию для cacerts.jks — «changeit»

Вывод

Целью данной статьи является документирование того, как установить безопасную связь SSL между сервером GlassFish EJB и веб-сервером GlassFish, используя сертификаты хранилища ключей со GlassFish 3.0.1. Эта цель была достигнута путем сначала документирования конфигурации модуля EJB, затем документирования конфигурации модуля WEB, а затем, наконец, документирования того, как обмениваться сертификатами между двумя серверами. Хотя в этой статье не указаны подробности о том, как на самом деле реализовать эти шаги, они должны содержать достаточно информации для интеграции в специфические настройки вашего кода / приложения / сервера. Конечно, комментируйте или связывайтесь со мной по любым вопросам.