Рубрики
Без рубрики

Руководство по Java GSS API

Краткий и практический обзор Java GSS Api.

Автор оригинала: Kumar Chandrakant.

1. Обзор

В этом уроке мы разберемся в Generic Security Service API (GSS API) и в том, как мы можем реализовать его в Java. Мы увидим, как мы можем защитить сетевую связь с помощью API GSS в Java.

В процессе мы создадим простые клиентские и серверные компоненты, защищая их с помощью GSS API.

2. Что Такое GSS API?

Итак, что же на самом деле представляет собой универсальный API службы безопасности? GSS API предоставляет общую платформу для приложений , которые могут использовать различные механизмы безопасности, такие как Kerberos , NTLM и SPNEGO, подключаемым способом. Следовательно, это помогает приложениям напрямую отделиться от механизмов безопасности.

Чтобы уточнить, безопасность здесь охватывает аутентификацию, целостность данных и конфиденциальность.

2.1. Зачем Нам Нужен GSS API?

Механизмы безопасности, такие как Kerberos, NTLM и Digest-MD5, сильно отличаются по своим возможностям и реализациям. Как правило, приложению, поддерживающему один из этих механизмов, довольно сложно переключиться на другой.

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

2.2. Как Работает GSS API?

GSS API-это механизм, основанный на токенах . Он работает путем обмена токенами безопасности между одноранговыми узлами . Этот обмен обычно происходит по сети, но API GSS не зависит от этих деталей.

Эти токены генерируются и обрабатываются конкретными реализациями API GSS. Синтаксис и семантика этих токенов специфичны для механизма безопасности, согласованного между одноранговыми узлами:

Центральная тема API GSS вращается вокруг контекста безопасности. Мы можем установить этот контекст между сверстниками посредством обмена токенами. Нам может потребоваться несколько обменов токенами между одноранговыми узлами для установления контекста.

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

3. Поддержка API GSS в Java

Java поддерживает GSS API как часть пакета “org.ietf.jgss”. Имя пакета может показаться странным. Это связано с тем, что привязки Java для API GSS определены в спецификации IETF . Сама спецификация не зависит от механизма безопасности.

Одним из популярных механизмов безопасности для Java GSS является Kerberos v5.

3.1. Java GSS API

Давайте попробуем понять некоторые основные API, которые создают Java GSS:

  • GSSContext инкапсулирует контекст безопасности API GSS и предоставляет службы, доступные в контексте
  • GSSCredential инкапсулирует учетные данные API GSS для сущности, необходимой для установления контекста безопасности
  • GSSName инкапсулирует основную сущность API GSS, которая обеспечивает абстракцию для различных пространств имен, используемых базовыми механизмами

Помимо вышеперечисленных интерфейсов, есть несколько других важных классов, которые следует отметить:

  • GSSManager служит заводским классом для других важных классов GSSAPI, таких как GSSName , GSSCredential и GSSContext
  • Oid представляет универсальные идентификаторы объектов (OID), которые являются иерархическими идентификаторами, используемыми в API GSS для идентификации механизмов и форматов имен
  • MessageProp обертывает свойства, чтобы указать GSSContext на такие вещи, как Качество защиты (QoP) и конфиденциальность для обмена данными
  • Привязка канала инкапсулирует дополнительную информацию о привязке канала, используемую для повышения качества, с которым обеспечивается аутентификация одноранговых сущностей

3.2. Поставщик безопасности Java GSS

Хотя Java GSS определяет основную структуру для реализации API GSS в Java, она не обеспечивает реализацию. Java использует Провайдер на основе подключаемых реализаций для служб безопасности включая Java GSS.

Может быть один или несколько таких поставщиков безопасности, зарегистрированных в архитектуре криптографии Java (JCA). Каждый поставщик безопасности может реализовать одну или несколько служб безопасности, таких как Java GSSAPI и механизмы безопасности под ними.

Существует поставщик GSS по умолчанию, который поставляется вместе с JDK. Однако существуют и другие поставщики GSS для конкретных поставщиков с различными механизмами безопасности, которые мы можем использовать. Одним из таких поставщиков является IBM Java GSS . Мы должны зарегистрировать такого поставщика безопасности в JCA, чтобы иметь возможность их использовать.

Кроме того, при необходимости мы можем реализовать нашего собственного поставщика безопасности с, возможно, пользовательскими механизмами безопасности . Однако на практике это вряд ли необходимо.

4. GSS API На примере

Теперь мы рассмотрим Java GSS в действии на примере. Мы создадим простое клиентское и серверное приложение. В GSS клиент чаще упоминается как инициатор, а сервер-как акцептор. Мы будем использовать Java GSS и Kerberos v5 ниже для аутентификации.

4.1. Контекст GSS для Клиента и сервера

Для начала нам нужно будет установить GSSContext как на сервере , так и на стороне клиента приложения.

Давайте сначала посмотрим, как мы можем сделать это на стороне клиента:

GSSManager manager = GSSManager.getInstance();
String serverPrinciple = "HTTP/[email protected]";
GSSName serverName = manager.createName(serverPrinciple, null);
Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");
GSSContext clientContext = manager.createContext(
  serverName, krb5Oid, (GSSCredential)null, GSSContext.DEFAULT_LIFETIME);
clientContext.requestMutualAuth(true);
clientContext.requestConf(true);
clientContext.requestInteg(true);

Здесь происходит довольно много вещей, давайте разберем их:

  • Мы начнем с создания экземпляра GSSManager
  • Затем мы используем этот экземпляр для создания GSSContext , передавая:

    • a GSSName , представляющий принципал сервера, обратите внимание конкретное имя принципала Kerberos здесь
    • Oid используемого механизма, Kerberos v5 здесь
    • учетные данные инициатора, null здесь означает, что будут использоваться учетные данные по умолчанию
    • время жизни для установленного контекста
  • Наконец, мы готовим контекст для взаимной аутентификации, конфиденциальности и целостности данных

Аналогично, мы должны определить контекст на стороне сервера:

GSSManager manager = GSSManager.getInstance();
GSSContext serverContext = manager.createContext((GSSCredential) null);

Как мы видим, это намного проще, чем контекст на стороне клиента. Единственное различие здесь заключается в том, что нам нужны учетные данные акцепторов, которые мы использовали как null . Как и прежде, null означает, что будут использоваться учетные данные по умолчанию.

4.2. Аутентификация GSS API

Хотя мы создали серверную и клиентскую части GSSContext , обратите внимание, что на данном этапе они не установлены.

Чтобы установить эти контексты, нам нужно обменяться токенами, специфичными для указанного механизма безопасности, то есть Kerberos v5:

// On the client-side
clientToken = clientContext.initSecContext(new byte[0], 0, 0);
sendToServer(clientToken); // This is supposed to be send over the network
		
// On the server-side
serverToken = serverContext.acceptSecContext(clientToken, 0, clientToken.length);
sendToClient(serverToken); // This is supposed to be send over the network
		
// Back on the client side
clientContext.initSecContext(serverToken, 0, serverToken.length);

Это, наконец, делает контекст установленным на обоих концах:

assertTrue(serverContext.isEstablished());
assertTrue(clientContext.isEstablished());

4.3. Защищенная связь GSS API

Теперь, когда у нас есть контекст, установленный на обоих концах, мы можем начать отправлять данные с целостностью и конфиденциальностью :

// On the client-side
byte[] messageBytes = "Baeldung".getBytes();
MessageProp clientProp = new MessageProp(0, true);
byte[] clientToken = clientContext.wrap(messageBytes, 0, messageBytes.length, clientProp);
sendToClient(serverToken); // This is supposed to be send over the network
       
// On the server-side 
MessageProp serverProp = new MessageProp(0, false);
byte[] bytes = serverContext.unwrap(clientToken, 0, clientToken.length, serverProp);
String string = new String(bytes);
assertEquals("Baeldung", string);

Здесь происходит несколько вещей, давайте проанализируем:

  • MessageProp используется клиентом для установки метода wrap и генерации токена
  • Метод wrap также добавляет криптографический микрофон данных, микрофон поставляется в комплекте как часть токена
  • Этот токен отправляется на сервер (возможно, по сетевому вызову)
  • Сервер снова использует MessageProp , чтобы установить метод unwrap и получить данные обратно
  • Кроме того, метод unwrap проверяет микрофон для полученных данных, обеспечивая целостность данных

Таким образом, клиент и сервер могут обмениваться данными с сохранением целостности и конфиденциальности.

4.4. Настройка Kerberos для примера

Теперь механизм GSS, такой как Kerberos, обычно должен извлекать учетные данные из существующего Субъекта . Класс Subject здесь представляет собой абстракцию JAAS, представляющую сущность, такую как человек или служба. Это обычно заполняется во время проверки подлинности на основе JAAS.

Однако в нашем примере мы не будем напрямую использовать аутентификацию на основе JAAS. Мы позволим Kerberos получать учетные данные напрямую, в нашем случае с помощью файла keytab. Для этого существует системный параметр JVM:

-Djavax.security.auth.useSubjectCredsOnly=false

Однако реализация Kerberos по умолчанию, предоставляемая Sun Microsystem, полагается на JAAS для обеспечения аутентификации.

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

com.sun.security.jgss.initiate  {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab=example.keytab
  principal="client/localhost"
  storeKey=true;
};
com.sun.security.jgss.accept  {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab=example.keytab
  storeKey=true
  principal="HTTP/localhost";
};

Эта конфигурация проста, где мы определили Kerberos как необходимый модуль входа как для инициатора, так и для акцептора. Кроме того, мы настроили использование соответствующих участников из файла keytab. Мы можем передать эту конфигурацию JAAS в JVM в качестве системного параметра:

-Djava.security.auth.login.config=login.conf

Здесь предполагается, что у нас есть доступ к KDC Kerberos. В KDC мы настроили необходимых участников и получили файл keytab для использования, скажем, “example.keytab”.

Кроме того, нам нужен файл конфигурации Kerberos, указывающий на правильный KDC:

[libdefaults]
default_realm = EXAMPLE.COM
udp_preference_limit = 1
[realms]
EXAMPLE.COM = {
    kdc = localhost:52135
}

Эта простая конфигурация определяет KDC, работающий на порту 52135, с областью по умолчанию как EXAMPLE.COM. Мы можем передать это в JVM в качестве системного параметра:

-Djava.security.krb5.conf=krb5.conf

4.5. Запуск примера

Чтобы запустить пример, мы должны использовать артефакты Kerberos, рассмотренные в предыдущем разделе .

Кроме того, нам нужно передать необходимые параметры JVM:

java -Djava.security.krb5.conf=krb5.conf \
  -Djavax.security.auth.useSubjectCredsOnly=false \
  -Djava.security.auth.login.config=login.conf \
  com.baeldung.jgss.JgssUnitTest

Этого достаточно для Kerberos, чтобы выполнить проверку подлинности с учетными данными из keytab и GSS для установления контекстов.

5. GSS API в реальном мире

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

  • Он широко используется в SASL в качестве механизма безопасности , особенно там, где Kerberos является основным механизмом выбора. Kerberos – это широко используемый механизм аутентификации, особенно в корпоративной сети. Действительно полезно использовать инфраструктуру Kerberized для проверки подлинности нового приложения. Следовательно, GSS API прекрасно устраняет этот пробел.
  • Он также используется в сопряжении с SPNEGO для согласования механизма безопасности, когда он заранее не известен. В этом отношении SPNEGO в некотором смысле является псевдомеханизмом GSS API. Это широко поддерживается во всех современных браузерах, что делает их способными использовать аутентификацию на основе Kerberos.

6. GSS API в сравнении

GSS API довольно эффективен в предоставлении служб безопасности приложениям с возможностью подключения. Однако это не единственный выбор для достижения этой цели в Java.

Давайте разберемся, что еще может предложить Java и как они сравниваются с GSS API:

  • Java Secure Socket Extension (JSSE): JSSE-это набор пакетов в Java, который реализует Secure Sockets Layer (SSL) для Java . Он обеспечивает шифрование данных, аутентификацию клиентов и серверов, а также целостность сообщений. В отличие от GSS API, JSSE полагается на инфраструктуру открытых ключей (PKI) для работы. Таким образом, API GSS оказывается более гибким и легким, чем JESSE.
  • Java Simple Authentication and Security Layer (SASL): SASL-это платформа для аутентификации и безопасности данных для интернет-протоколов , которая отделяет их от конкретных механизмов аутентификации. Это похоже по объему на GSS API. Однако Java GSS имеет ограниченную поддержку базовых механизмов безопасности через доступных поставщиков безопасности.

В целом, GSS API довольно эффективен в предоставлении услуг безопасности в агностической манере. Тем не менее, поддержка большего количества механизмов безопасности в Java будет способствовать дальнейшему внедрению.

7. Заключение

Подводя итог, в этом уроке мы поняли основы GSS API как основы безопасности. Мы изучили Java API для GSS и поняли, как мы можем их использовать. В процессе мы создали простые клиентские и серверные компоненты, которые выполняли взаимную аутентификацию и безопасно обменивались данными.

Кроме того, мы также рассмотрели, каковы практические приложения API GSS и какие альтернативы доступны в Java.

Как всегда, код можно найти на GitHub .