Разные guish запросы между несколькими разъемами / портами во встроенном Tomcat в Spring Boot - PullRequest
1 голос
/ 11 февраля 2020

У меня есть приложение на основе службы отдыха Spring Boot, настроенное на несколько портов, которое должно различать guish каждый запрос между портом, через который он прошел. Идея иметь несколько портов для приложения обусловлена ​​тем, что разные публичные c и частные подсети (с разными уровнями доступа к безопасности) могут получать доступ к различным частям служб, предоставляемых приложением.

Концептуально Идея состояла в том, чтобы добавить дополнительные коннекторы во встроенный tomcat, а затем перехватить все входящие запросы, изменив их, добавив в каждый из них настраиваемый заголовок, указав «канал», через который он прошел.

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

Итак, для многопортового решения у меня есть:

@Configuration
public class EmbeddedTomcatConfiguration {

    @Value("${server.additional-ports}")
    private String additionalPorts;

    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        Connector[] additionalConnectors = additionalConnector();
        if(additionalConnectors != null && additionalConnectors.length > 0) {
            tomcat.addAdditionalTomcatConnectors(additionalConnectors);
        }
        return tomcat;
    }

    private Connector[] additionalConnector() {
        if(StringUtils.isNotBlank(additionalPorts)) {
            return Arrays.stream(additionalPorts.split(","))
                .map(String::trim)
                .map(p -> {
                    Connector connector = new Connector(Http11NioProtocol.class.getCanonicalName());
                    connector.setScheme("http");
                    connector.setPort(Integer.valueOf(p));
                    return connector;
                })
                .toArray(Connector[]::new);
        }
        return null;
    }
}

Теоретически, я мог бы зарегистрировать пользовательский LifecycleListener для каждого разъема, но, насколько я знаю, это не поможет. Я также слышал кое-что о клапанах, хотя я не уверен, как реализовать их для каждого разъема.

Или, может быть, я иду совершенно неверным путем.

Я бы очень признателен любая помощь в этом вопросе.

1 Ответ

1 голос
/ 12 февраля 2020

Кажется, у вас есть желание попробовать Valve, но после еще нескольких исследований я бы порекомендовал использовать ServletFilter для этой работы вместо Valve.

Я полагаю, что вы можете сделать это работает в Valve, но Valve должен быть развернут в каталоге tomcat / lib, а не упакован внутри вашего приложения. Я бы настоятельно рекомендовал вам попытаться сохранить ваше приложение вместе в развертываемом артефакте вместо того, чтобы не забыть развернуть один дополнительный файл JAR на экземпляре tomcat при создании нового развертывания.

Из этого ответа Разница между getLocalPort () и getServerPort () в сервлетах вы сможете получить доступ к порту tomcat, вызвав getLocalPort () для HttpServletRequest.

Затем, основываясь на вашей идее в вопросе, добавьте указать c имя контекста в заголовке запроса .

public class PortContextFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        int localPort = request.getLocalPort();

        // if else or case statements

        ServletRequest newRequest = PortContextHttpServletRequestWrapper(request, YourPortContext)

        filterChain.doFilter(newRequest, response);
    }

    public void destroy() {
        // Nothing to do
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        // Nothing to do.
    }

}

Теоретически после этого вы сможете использовать аннотацию @RequestMapping для маршрутизации на основе имени внутри заголовка. .

@PreAuthorize("hasPermission(#your_object, 'YOUR_OBJECT_WRITE')")
@RequestMapping("/yourobject/{identifier}", headers="context=<context_name>", method = RequestMethod.POST)
public String postYourObject(@PathVariable(value = "identifier") YourObject yourObject) {
    // Do something here...
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...