Как я могу указать свой файл.keystore с помощью Spring Boot и Tomcat?

Я пытаюсь настроить Spring Security для работы со встроенным экземпляром Spring Boot Tomcat. Существует довольно много базовых примеров, которые делают это, но я застрял там, где они заканчиваются - они выполняют базовую аутентификацию через HTTP (не HTTPS).

Я мог бы, вероятно, заставить его работать, если бы у меня был доступ к файлам конфигурации Tomcat (server.xml) но поскольку Spring Boot использует встроенный экземпляр Tomcat (что в противном случае является очень удобным), у меня нет доступа к файлам конфигурации Tomcat (по крайней мере, насколько мне известно).

Там может быть application.properties настройка для этого, но я не смог отследить его. Я видел ссылки на server.contextPath поле в application.properties я подозреваю, что это может быть связано с заменой файлов конфигурации Tomcat. Даже если это связано, я не знаю, с чего начать - все инструкции Tomcat SSL, которые я видел, начинаются с редактирования существующего server.xml файл, а не создание с нуля.

Можно ли это сделать с помощью Spring Boot (либо указав фрагмент кода server.xml или другими способами)? Если нет, то какой самый простой способ сделать это? Я понимаю, что мне может потребоваться исключить компонент Tomcat в Spring Boot, но я бы предпочел избежать этого, если это возможно.

5 ответов

Решение

Оказывается, есть способ сделать это, хотя я не уверен, что нашел "правильный" способ, так как для этого требовались часы чтения исходного кода из нескольких проектов. Другими словами, это может быть много глупой работы (но это работает).

Во-первых, нет никакого способа получить доступ к server.xml во встроенном Tomcat, чтобы увеличить или заменить его. Это должно быть сделано программно.

Во-вторых, настройка 'require_https' не помогает, так как вы не можете установить информацию сертификата таким образом. Он настраивает переадресацию с http на https, но не дает вам способа заставить https работать, поэтому пересылка бесполезна. Тем не менее, используйте его с приведенным ниже материалом, который заставляет https работать.

Для начала вам необходимо предоставить EmbeddedServletContainerFactory как объясняется в документации по поддержке встроенного контейнера сервлетов. Документы для Java, но Groovy будет выглядеть примерно так же. Обратите внимание, что я не смог заставить его распознать @Value аннотация используется в их примере, но это не нужно. Для groovy просто поместите это в новый файл.groovy и включите этот файл в командную строку при запуске spring загрузки.

Теперь инструкции говорят, что вы можете настроить TomcatEmbeddedServletContainerFactory класс, который вы создали в этом коде, чтобы вы могли изменить поведение web.xml, и это правда, но для наших целей важно знать, что вы также можете использовать его для адаптации server.xml поведение. Действительно, читая исходный код класса и сравнивая его с документами Embedded Tomcat, вы видите, что это единственное место, где это можно сделать. Интересная функция TomcatEmbeddedServletContainerFactory.addConnectorCustomizers(), который может не сильно походить на Javadocs, но на самом деле дает вам встроенный объект Tomcat для индивидуальной настройки. Просто пройдите вашу собственную реализацию TomcatConnectorCustomizer и установить то, что вы хотите на данный Connector в void customize(Connector con) функция. Теперь есть около миллиарда вещей, которые вы можете сделать с Connector и я не мог найти полезные документы для этого, но createConnector() Работайте в этом личном проекте Spring -edded-Tomcat, это очень практическое руководство. Моя реализация в итоге выглядела так:

package com.deepdownstudios.server

import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory
import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.boot.*
import org.springframework.stereotype.*

@Configuration
class MyConfiguration {

@Bean
public EmbeddedServletContainerFactory servletContainer() {
final int port = 8443;
final String keystoreFile = "/path/to/keystore"
final String keystorePass = "keystore-password"
final String keystoreType = "pkcs12"
final String keystoreProvider = "SunJSSE"
final String keystoreAlias = "tomcat"

TomcatEmbeddedServletContainerFactory factory = 
        new TomcatEmbeddedServletContainerFactory(this.port);
factory.addConnectorCustomizers( new TomcatConnectorCustomizer() {
    void    customize(Connector con) {
        Http11NioProtocol proto = (Http11NioProtocol) con.getProtocolHandler();
            proto.setSSLEnabled(true);
        con.setScheme("https");
        con.setSecure(true);
        proto.setKeystoreFile(keystoreFile);
        proto.setKeystorePass(keystorePass);
        proto.setKeystoreType(keystoreType);
        proto.setProperty("keystoreProvider", keystoreProvider);
        proto.setKeyAlias(keystoreAlias);
    }
});
return factory;
}
}

Autowiring подхватит эту реализацию и запустит ее. Как только я исправил свой поврежденный файл хранилища ключей (обязательно вызовите keytool с помощью -storetype pkcs12 не -storepass pkcs12 как сообщалось в другом месте), это сработало. Кроме того, было бы гораздо лучше предоставить параметры (порт, пароль и т. Д.) В качестве параметров конфигурации для тестирования и т. Д. Я уверен, что это возможно, если вы можете использовать аннотацию @Value для работы с Groovy.

Начиная с Spring Boot 1.2, вы можете настроить SSL с помощью application.properties или же application.yml, Вот пример для application.properties:

server.port = 8443
server.ssl.key-store = classpath:keystore.jks
server.ssl.key-store-password = secret
server.ssl.key-password = another-secret

То же самое с application.yml:

server:
  port: 8443
  ssl:
    key-store: classpath:keystore.jks
    key-store-password: secret
    key-password: another-secret

Вот ссылка на текущую справочную документацию.

Для внешних хранилищ ключей используйте префикс "file:"

server.ssl.key-store=file:config/keystore 

Если вы не хотите реализовывать свои connector customizerвы можете собрать и импортировать библиотеку ( https://github.com/ycavatars/spring-boot-https-kit), которая предоставляет предопределенные connector customizer, Согласно README, вам нужно только создать хранилище ключей, настроить connector.https.*, импортировать библиотеку и добавить @ComponentScan("org.ycavatars.sboot.kit"), Тогда у вас будет соединение HTTPS.

Другие вопросы по тегам