Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Выполнение примера встроенного хранилища идентификаторов базы данных

Пример, описанный в этом разделе, демонстрирует, как использовать встроенное хранилище идентификаторов базы данных для проверки учётных данных.

Темы включают в себя:

Обзор примера built-in-db-identity-store

JSR 375 требует ОБЯЗАТЕЛЬНОЙ поддержки контейнером Java EE встроенного IdentityStore базы данных. Для поддержки этого обязательного требования DatabaseIdentityStore связан с GlassFish.

В этом примере демонстрируется, как вы можете настроить DatabaseIdentityStore, чтобы он указывал на встроенную базу данных, а затем использовал её в качестве IdentityStore. Используемый механизм аутентификации — BasicAuthenticationMechanism.

Исходный код для этого примера находится в каталоге tut-install/examples/security/security-api/built-in-db-identity-store.

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

Когда запрос, содержащий учётные данные, отправляется приложению, он запускает настроенный механизм проверки подлинности, и проверка подлинности выполняется для DatabaseIdentityStore, как определено в приложении.

После проверки подлинности приложение также проверяет роли вызывающего субъекта и отправляет подробности как часть ответа.

Обратите внимание, что в GlassFish, если пользователь предоставляет неверные учётные данные при использовании BasicAuthenticationMechanism, то realmName представляется пользователю в качестве подсказки.

curl -I -u Joe http://localhost:8080/built-in-db-identity-store/servlet
Enter host password for user 'Joe':
HTTP/1.1 401 Unauthorized
Server: GlassFish Server Open Source Edition  5.0
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition  5.0  Java/Oracle Corporation/1.8)
WWW-Authenticate: Basic realm="file"
Content-Length: 1090
Content-Language:
Content-Type: text/html

Определите пользователей и группы в хранилище идентификаторов

В следующей таблице показаны пользователи, пароли и группы, используемые в этом примере.

Пользователь

Пароль

Группа

Joe

secret1

foo, bar

Sam

secret2

foo, bar

Tom

secret2

foo

Sue

secret2

foo

В следующем коде показано, как определить учётные данные и роли, назначенные пользователям в файле DatabaseSetup.java.

С аннотацией @Startup этот Enterprise-бин-синглтон инициализируется во время запуска приложения, а учётные данные устанавливаются в базу данных.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.annotation.sql.DataSourceDefinition;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.sql.DataSource;

@Singleton
@Startup
public class DatabaseSetup {

    // Источник данных по умолчанию, предустановленный в GlassFish и использующийся для хранений данных аутентификации.
    @Resource(lookup="java:comp/DefaultDataSource")
    private DataSource dataSource;

    @PostConstruct
    public void init() {

        // ...
        executeUpdate(dataSource, "INSERT INTO caller VALUES('Joe', '" + passwordHash.generate("secret1".toCharArray()) + "')");
        // ...
        executeUpdate(dataSource, "INSERT INTO caller_groups VALUES('Joe', 'foo')");
        executeUpdate(dataSource, "INSERT INTO caller_groups VALUES('Joe', 'bar')");
        // ...
    }

    @PreDestroy
    public void destroy() {
    	// ...
    }

    private void executeUpdate(DataSource dataSource, String query) {
        // ...
    }
}

Связывание DatabaseIdentityStore с источником данных по умолчанию

Используйте аннотацию @DatabaseIdentityStoreDefinition для связи встроенного DatabaseIdentityStore с DefaultDataSource в файле ApplicationConfig.java. Этот пример также демонстрирует использование интерфейса Pbkdf2PasswordHash.

// Определение базы данных для предустановленного DatabaseIdentityStore
@DatabaseIdentityStoreDefinition(
    callerQuery = "#{'select password from caller where name = ?'}",
    groupsQuery = "select group_name from caller_groups where caller_name = ?",
    hashAlgorithm = Pbkdf2PasswordHash.class,
    priorityExpression = "#{100}",
    hashAlgorithmParameters = {
        "Pbkdf2PasswordHash.Iterations=3072",
        "${applicationConfig.dyna}"
    }
)

@ApplicationScoped
@Named
public class ApplicationConfig {

  public String[] getDyna() {
       return new String[]{"Pbkdf2PasswordHash.Algorithm=PBKDF2WithHmacSHA512", "Pbkdf2PasswordHash.SaltSizeBytes=64"};
   }

}

Укажите механизм аутентификации

В этом приложении учётные данные проверяются с использованием механизма базовой аутентификации. Укажите аннотацию @BasicAuthenticationMechanismDefinition в ApplicationConfig.java, чтобы убедиться, что BasicAuthenticationMechanism используется для выполнения проверки учётных данных.

Когда выполняется запрос к сервлету, о котором идёт речь, контейнер делегирует его в org.glassfish.soteria.mechanisms.jaspic.HttpBridgeServerAuthModule, который затем вызывает метод BasicAuthenticationMechanism.validateRequest и получает учётные данные из запроса.

@BasicAuthenticationMechanismDefinition(
        realmName = "file"
)

Объявите роли в контейнере сервлетов

Когда к приложению делается запрос, назначенные пользователю роли возвращаются как часть ответа. Обратите внимание, что контейнер должен быть осведомлён о поддерживаемых ролях, которые определяются с помощью аннотации @DeclareRoles({"foo", "bar", "kaz"}), как показано ниже.

@WebServlet("/servlet")
@DeclareRoles({ "foo", "bar", "kaz" })
@ServletSecurity(@HttpConstraint(rolesAllowed = "foo"))
public class Servlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String webName = null;
        if (request.getUserPrincipal() != null) {
            webName = request.getUserPrincipal().getName();
        }

        response.getWriter().write("web username: " + webName + "\n");

        response.getWriter().write("web user has role \"foo\": " + request.isUserInRole("foo") + "\n");
        response.getWriter().write("web user has role \"bar\": " + request.isUserInRole("bar") + "\n");
        response.getWriter().write("web user has role \"kaz\": " + request.isUserInRole("kaz") + "\n");
    }

}

В GlassFish 5.0 назначение группы ролям по умолчанию включено. Поэтому не требуется связывать web.xml с приложением, чтобы обеспечить назначение ролей группам.

Запуск built-in-db-identity-store

Вы можете использовать IDE NetBeans или Maven для сборки, упаковки, развёртывания и запуска приложения built-in-db-identity-store, как описано в следующих разделах:

Сборка, упаковка и развёртывание built-in-db-identity-store с IDE NetBeans

  1. Если вы ещё этого не сделали, запустите базу данных по умолчанию. Это необходимо, потому что мы используем DefaultDataSource в комплекте с GlassFish для DatabaseIdentityStore. Смотрите Запуск и остановка Apache Derby.

  2. Если вы ещё этого не сделали, запустите сервер GlassFish. Смотрите Запуск и остановка сервера GlassFish.

  3. В меню «Файл» выберите «Открыть проект».

  4. В диалоговом окне «Открыть проект» перейдите к:

    tut-install/examples/security/security-api
  5. Выберите каталог built-in-db-identity-store.

  6. Нажмите Открыть проект.

  7. На вкладке «Проекты» кликните правой кнопкой мыши проект built-in-db-identity-store и выберите «Сборка».

    Эта команда собирает и развёртывает пример приложения в GlassFish Server.

Сборка, упаковка и развёртывание built-in-db-identity-store с использованием Maven

  1. Если вы ещё этого не сделали, запустите базу данных по умолчанию. Это необходимо, потому что мы используем DefaultDataSource в комплекте с GlassFish для DatabaseIdentityStore. Смотрите Запуск и остановка Apache Derby.

  2. Если вы ещё этого не сделали, запустите сервер GlassFish. Смотрите Запуск и остановка сервера GlassFish.

  3. В окне терминала перейдите в:

    tut-install/examples/security/security-api/built-in-db-identity-store
  4. Введите следующую команду:

    mvn install

    Эта команда собирает и упаковывает приложение в WAR-файл built-in-db-identity-store.war, который находится в каталоге target, а затем развёртывает этот WAR-файл.

Запуск built-in-db-identity-store

В этом примере используйте учётные данные пользователя Joe, чтобы сделать запрос и проверить ответ в соответствии с учётными данными/ролями, определёнными в DatabaseSetup.java.

  1. Сделайте запрос к развёрнутому приложению, введя следующий URL запроса в вашем веб-браузере:

    URL запроса:

    http://localhost:8080/built-in-db-identity-store/servlet

    Поскольку здесь используется BASIC-аутентификация, контейнер отвечает обратно, запрашивая имя пользователя и пароль.

  2. Введите имя пользователя Joe и пароль secret1 в командной строке.

    После предоставления учётных данных происходит следующий процесс:

    • Клиент представляет запрос контейнеру со строкой в ​​кодировке base64 и с заголовком Authorization, используя значение в формате, ожидаемом для базовой аутентификации.

    • Когда имя пользователя и пароль доступны для контейнера, проверка выполняется в DatabaseIdentityStore.

    • Соответствующий объект UsernamePasswordCredential передаётся в качестве параметра методу DatabaseIdentityStore.validate().

    • Пароль извлекается из базы данных для пользователя Joe.

    • Пароль, хранящийся в базе данных, хэшируется с использованием алгоритма PBKDF2 и проверяется встроенной реализацией Pbkdf2PasswordHash.

    • При успешной проверке запрос передаётся соответствующему сервлету, а конечному пользователю возвращается следующий ответ.

      Ответ:

      web username: Joe
      web user has role "foo": true
      web user has role "bar": true
      web user has role "kaz": false
  3. Проверьте аутентификацию, используя недействительные учётные данные. Сделайте запрос к развёрнутому приложению, введя следующий URL запроса в вашем веб-браузере:

    URL запроса:

    http://localhost:8080/built-in-db-identity-store/servlet

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

  4. Введите неверное имя пользователя и пароль. Вам предлагается снова ввести учётные данные, так как вы не прошли аутентификацию.

    При клике кнопки «Отмена» в окне «Требуется аутентификация» возвращается следующий ответ:

    HTTP Status 401 — Unauthorized
    
    type Status report
    
    message Unauthorized
    
    description This request requires HTTP authentication.
    
    GlassFish Server Open Source Edition 5

Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)