Spring Security предусматривает пакет, способный делегировать запросы на аутентификацию сервису Аутентификации и Авторизации Java (JAAS). Этот пакет подробно описан ниже.

AbstractJaasAuthenticationProvider

AbstractJaasAuthenticationProvider является основой для предусмотренных реализаций AuthenticationProvider в JAAS. Подклассы должны реализовать метод, который создает LoginContext. AbstractJaasAuthenticationProvider имеет ряд зависимостей, которые могут быть введены в него и которые описаны ниже.

JAAS CallbackHandler

Большинству LoginModule из JAAS требуется какой-то тип обратного вызова. Эти обратные вызовы обычно используются для получения имени пользователя и пароля от пользователя.

При развертывании с использованием Spring Security, Spring Security отвечает за это взаимодействие с пользователем (через механизм аутентификации). Таким образом, к моменту передачи запроса аутентификации в JAAS, механизм аутентификации Spring Security уже полностью заполнит объект Authentication, содержащий всю информацию, необходимую LoginModule из JAAS.

Поэтому пакет JAAS для Spring Security содержит два стандартных обработчика обратных вызовов, JaasNameCallbackHandler и JaasPasswordCallbackHandler. Каждый из этих обработчиков обратного вызова реализует JaasAuthenticationCallbackHandler. В большинстве случаев эти обработчики обратного вызова можно просто использовать и не разбираться в их внутренней механике.

Для тех, кому требуется полный контроль над логикой работы обратного вызова, на внутреннем уровне AbstractJaasAuthenticationProvider обёртывает эти экземпляры JaasAuthenticationCallbackHandler с помощью InternalCallbackHandler. InternalCallbackHandler – это класс, который фактически реализует обычный интерфейс CallbackHandler из JAAS. При каждом использовании LoginModule из JAAS ему передается список экземпляров InternalCallbackHandler, сконфигурированных в контексте приложения. Если LoginModule запрашивает обратный вызов для InternalCallbackHandlers, обратный вызов, в свою очередь, передается обертываемым экземплярам JaasAuthenticationCallbackHandler.

JAAS AuthorityGranter

JAAS работает с принципалами. В JAAS даже "роли" представлены в виде принципалов. Spring Security, с другой стороны, работает с объектами Authentication. Каждый объект Authentication содержит одного принципала и несколько GrantedAuthority. Чтобы упростить сопоставление между этими различными понятиями, пакет JAAS в Spring Security содержит интерфейс AuthorityGranter.

AuthorityGranter отвечает за проверку принципала JAAS и возвращает набор String, представляющих полномочия, переданные принципалу. Для каждой возвращенной строки разрешений, AbstractJaasAuthenticationProvider создает JaasGrantedAuthority (который реализует интерфейс GrantedAuthority из Spring Security), содержащий строку полномочий и принципала JAAS, который был передан AuthorityGranter. AbstractJaasAuthenticationProvider получает принципалов JAAS, сначала успешно аутентифицируя учетные данные пользователя с помощью LoginModule из JAAS, а затем обращаясь к возвращаемому LoginContext. Выполняется вызов LoginContext.getSubject().getPrincipals(), при этом каждый полученный принципал передается каждому AuthorityGranter, определенному в свойстве AbstractJaasAuthenticationProvider.setAuthorityGranters(List).

Spring Security не содержит никаких производственных AuthorityGranters, поскольку каждый принципал JAAS имеет специфическое для конкретной реализации значение. Однако в модульных тестах есть TestAuthorityGranter, который наглядно демонстрирует работу простой реализации AuthorityGranter.

DefaultJaasAuthenticationProvider

DefaultJaasAuthenticationProvider позволяет внедрить в него JAAS-объект Configuration в качестве зависимости. Затем он создает LoginContext, используя внедренную Configuration из JAAS. Это значит, что DefaultJaasAuthenticationProvider не связан с какой-то конкретной реализацией Configuration, как JaasAuthenticationProvider.

InMemoryConfiguration

Чтобы упростить внедрение Configuration в DefaultJaasAuthenticationProvider, по умолчанию предусмотрена размещаемая в оперативной памяти реализация с именем InMemoryConfiguration. Конструктор реализации принимает Map, в которой каждый ключ представляет имя конфигурации входа в систему, а значение – Array, состоящий из AppConfigurationEntry. InMemoryConfiguration также поддерживает стандартный Array, состоящий из объектов AppConfigurationEntry, который будет использован, если не будет найдено отображение в указанной Map. За подробностями обратитесь к javadoc на уровне классов по InMemoryConfiguration.

Пример конфигурации DefaultJaasAuthenticationProvider

Хотя конфигурация Spring для InMemoryConfiguration может быть более перегруженной, чем стандартные конфигурационные JAAS-файлы, ее использование в сочетании с DefaultJaasAuthenticationProvider является более гибким, чем использование JaasAuthenticationProvider, поскольку она не зависит от стандартной реализации Configuration.

Ниже приведен пример конфигурации DefaultJaasAuthenticationProvider с использованием InMemoryConfiguration. Обратите внимание, что кастомные реализации Configuration с легкостью можно внедрить и в DefaultJaasAuthenticationProvider.

<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<property name="configuration">
<bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
	<map>
	<!--
	SPRINGSECURITY является loginContextName по умолчанию
	для AbstractJaasAuthenticationProvider
	-->
	<entry key="SPRINGSECURITY">
	<array>
	<bean class="javax.security.auth.login.AppConfigurationEntry">
		<constructor-arg value="sample.SampleLoginModule" />
		<constructor-arg>
		<util:constant static-field=
			"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/>
		</constructor-arg>
		<constructor-arg>
		<map></map>
		</constructor-arg>
		</bean>
	</array>
	</entry>
	</map>
	</constructor-arg>
</bean>
</property>
<property name="authorityGranters">
<list>
	<!-- Необходимо будет написать собственную реализацию AuthorityGranter -->
	<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>

JaasAuthenticationProvider

JaasAuthenticationProvider предполагает, что стандартная Configuration является экземпляром ConfigFile. Такое предположение делается для того, чтобы предпринимать попытки обновить Configuration. Затем JaasAuthenticationProvider использует стандартную Configuration для создания LoginContext.

Предположим, что у нас есть конфигурационный JAAS-файл для входа в систему, /WEB-INF/login.conf, со следующим содержимым:

JAASTest {
	sample.SampleLoginModule required;
};

Как и все бины Spring Security, JaasAuthenticationProvider конфигурируется через контекст приложения. Следующие определения будут соответствовать приведенному выше конфигурационному JAAS-файлу входа в систему:

<bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/>
<property name="loginContextName" value="JAASTest"/>
<property name="callbackHandlers">
<list>
<bean
	class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
<bean
	class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
</list>
</property>
<property name="authorityGranters">
	<list>
	<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
	</list>
</property>
</bean>

Выполнение в качестве Subject

JaasApiIntegrationFilter – если добавлен в конфигурацию – будет пытаться выполняться как Subject для JaasAuthenticationToken. Это означает, что доступ к Subject можно получить с помощью:

Subject subject = Subject.getSubject(AccessController.getContext());

Эту интеграцию можно с легкостью сконфигурировать при помощи атрибута jaas-api-provision. Эта функция полезна при интеграции с устаревшими или внешними API, которые основываются на заполнении JAAS-субъекта.