如何在spring Boot rest控制器中只在某些端点上启用http,而在其他一些端点上启用https?

hyrbngr7  于 2022-12-04  发布在  Spring
关注(0)|答案(1)|浏览(147)

我想在某些端点上启用http,在另一组端点上启用https
我得到了一些解决方案,比如通过application.properties配置https,通过编程方式创建一个额外的连接器配置http,但是所有结果都为所有端点启用了httphttps
有人能告诉我如何使用https配置某些端点,以及使用http配置某些端点吗?

soat7uwm

soat7uwm1#

我为我使用的Jettyservlet计算出了这一点。如果您使用默认的TomCat servlet,您将不得不做一些类似的工作,我想这对TomCat有效。
首先,我有一个ssl端口作为默认端口。要允许http,您需要在配置中配置一个额外的http端口。然后,您需要添加一个服务器处理程序。您可以添加处理程序SecuredRedirectHandler将所有http请求重定向到https端口。由于我们不想重定向所有http请求,因此我们创建了自己的CustomRedirectHandler,它扩展了SecuredRedirectHandler。

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
    factory.addServerCustomizers(new JettyServerCustomizer() {
        @Override
        public void customize(Server server) {
            final HttpConnectionFactory httpConnectionFactory = server.getConnectors()[0].getConnectionFactory(HttpConnectionFactory.class);
            // Enable HTTP for assigned port
            final ServerConnector httpConnector = new ServerConnector(server, httpConnectionFactory);
            httpConnector.setPort(serverProperties.intHttpPort() /* HTTP */);
            server.addConnector(httpConnector);
            // Add a CustomRedirectHandler to Server Handlers
            final HandlerList handlerList = new HandlerList();
            handlerList.addHandler(new CustomRedirectHandler());
            for(Handler handler : server.getHandlers()) {
                handlerList.addHandler(handler);
            }
            server.setHandler(handlerList);
        }
    });
    return factory;
}

在我们的CustomRedirectHandler中,我们可以检查请求的端点是否在我们的“允许的http”数组中。如果它已经请求了https或者被允许http,那么我们什么也不做,否则重定向到https。我的示例只允许http用于以“/.well-known/acme-challenge/”开头的端点,以允许例如对http://example.com/.well-known/acme-challenge/TOKEN的请求。

public class CustomRedirectHandler extends SecuredRedirectHandler {
    
    private final String[] allowedHttp = {"/.well-known/acme-challenge/"};
    
    @Override
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        HttpChannel channel = baseRequest.getHttpChannel();
        if (baseRequest.isSecure() || channel == null) {
            // nothing to do, already requested https
            return;
        }
        // Check if request is for allowed http
        if (allowHttp(baseRequest)) {
            return;
        }
        // Else Redirect to https
        super.handle(target, baseRequest, request, response);
    }

    public boolean allowHttp(Request baseRequest) {
        String pathInfo = baseRequest.getPathInfo();
        if (pathInfo == null) {
            return false;
        }
        for (String allowed : allowedHttp) {
            if (pathInfo.startsWith(allowed)) {
                return true;
            }
        }
        return false;
    }
    
    
}

相关问题