Аутентификация пользователей

Начиная с JDK 1.4, в состав Java 2 Standart Edition была включена служба Java Authentication and Authorization Service (JAAS). В названии службы слово "аутентификация" (authentication) относится к пользователям, т.е. программа получает возможность идентифицировать пользователя, работающего с ней. Слово "авторизация" (authorization) означает возможность связывания с пользователями различных наборов привелегий.

Служба JAAS представляет собой встраиваемый API, который изолирует Java-приложение от средства аутентификации. Помимо прочего, он поддерживает регистрацию для систем UNIX и NT, а также аутентификацию на базе Kerberos и на базе сертификатов.

Если пользователь аутентифицирован, с ним можно связать определенные права доступа. Ниже приведен пример присвоения пользователю с именем Harry всех прав доступа к файлам.

grant principal com.sun.security.auth.UnixPrincipal "Harry"
{
  permission java.util.PropertyPermission "user.*", "read";
  . . .
};

Здесь класс com.sun.security.auth.UnixPrincipal проверяет имя пользователя системы UNIX, который работает с данной программой. Метод getName данного класса возвращает учетное имя пользователя, после чего проверяется, совпадает ли оно с именем Harry.
Для того, чтобы дать диспетчеру защиты возможность проверять предоставляемые права, используется класс LoginContext. Ниже приведен типичный пример кода, обеспечивающего регистрацию.

try
{
  System.setSecurityManager (new SecurityManager ());
  LoginContext context = new LoginContext ("Login1");
  // Определен в конфигурационном файле JAAS
  context.login ();
  // Получить аутентифицированный объект Subject
  Subject subject = context.getSubject ();
  . . .
  context.logout ();
}
catch (LoginException exception) // Исключение генерируется
{
  // Если попытка регистрации оказалась неудачной
  exception.printStackTrace ();
}

Теперь переменная subject соответствует аутентифицированному пользователю. Строковый параметр "Login1" в конструкторе LoginContext соответствует записи с таким же именем в конфигурационном файле JAAS. Типичный конфигурационный файл показан ниже.

Login1
{
  com.sun.security.auth.module.UnixLoginModule required;
  com.whizzbang.auth.module.RetinaScanModule sufficient;
}
 
Login2
{
  . . .
}

Конечно, в JDK не предусмотрена биометрическая аутентификация. В пакете com.sun.security.auth.module содержатся следующие модули:

  UnixLoginModule
  NTLoginModule
  Krb5LoginModule
  JndiLoginModule
  KeyStoreLoginModule

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

Учетная запись аутентифицирует субъект(subject), который может иметь несколько принципалов (principals). Принципал описывает некоторое свойство субъекта, например регистрационное имя, идентификатор группы или роль. Как показано в выражении grant, принципалы управляют правами доступа. Объект com.sun.security.auth.UnixPrincipal описывает регистрационное имя UNIX, а UnixNumericGroupPrincipal может выполнить проверку на принадлежность группе UNIX.

Выражение grant проверяет принципал c помощью следующего выражения:

grant класс_принципала "имя_принципала"

Пример такого выражения приведен ниже.

grant com.sun.security.auth.UnixProncipal "Harry"

При регистрации пользователя в системе необходимо запустить код, который потребует выполнения проверки принципалов в отдельном контексте управления доступом. Для запуска нового привелегированного действия PrivilegedAction () нужно использовать статический метод doAs () или doAsPrivileged (). Оба указанных метода выполняют действие путем вызова метода run () объекта, реализующего интерфейс PrivilegedAction. Данный интерфейс использует права принципиала.

PrivilegedAction action = new PrivilegedAction ()
{
  public Object run ()
  {
   // Использование прав принципалов
   . . .
  }
}
Subject.doAsPrivileged (subject, action, null);
// или doAs (subject, action)

Если указанный код приводит к появлению исключения, то вместо него придется реализовать интерфейс PrivilegedExceptionAction.
Методы doAs () и doAsPrivileged () отличаются друг от друга лишь отдельными деталями. Метод doAs () запускается в текущем контексте управления доступом, а метод doAsPrivileged () выполняется в заданном контексте. Кроме того, метод doAsPrivileged () позволяет разделять права для регистрационного кода и бизнес-логики. В нашем примере регистрационный код имеет следующие полномочия :

permission javax.security.auth.AuthPermission "createLoginCintext.Login1";
permission javax.security.auth.AuthPermission "doAsPrivileged";

Аутентификационный пользователь имеет права, определяемые выражением:

permission java.util.PropertyPermission "user.*", "read";

Если бы вместо doAsPrivileged () мы использовали метод doAs (), регистрационному коду потребовались бы те же права.