How to enable only http on some endpoints and https on some other endpoints in a spring boot rest controller?

huangapple go评论71阅读模式
英文:

How to enable only http on some endpoints and https on some other endpoints in a spring boot rest controller?

问题

我想在一些端点上启用 http,并在另一组端点上启用 https

我得到了一些解决方案,比如通过 application.properties 配置 https,并通过以编程方式创建额外连接器来配置 http,但所有的结果都会对所有端点同时启用 httphttps

有人可以告诉我如何配置一些端点为 https,另一些端点为 http 吗?

英文:

I want to enable http on some endpoints and https on another set of endpoints.

I got solutions like configure https through application.properties and http by programmatically creating an extra connector, but all the results enable both http and https for all endpoints.

Can someone let me know how to configure some endpoints with https and some end points with http?

答案1

得分: 1

我已经为我使用的**Jetty** servlet解决了这个问题如果你使用默认的TomCat servlet你可能需要进行类似的操作来适用于TomCat

首先我将ssl端口设置为默认激活状态为了允许http访问您需要在配置中配置一个额外的http端口然后您需要添加一个服务器处理程序Handler)。您可以添加"SecuredRedirectHandler"处理程序将所有http请求重定向到https端口由于我们不想重定向所有http请求我们创建了一个自定义的"CustomRedirectHandler"它继承自"SecuredRedirectHandler"

```java
@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);
            // 启用指定端口的HTTP
            final ServerConnector httpConnector = new ServerConnector(server, httpConnectionFactory);
            httpConnector.setPort(serverProperties.intHttpPort() /* HTTP */);
            server.addConnector(httpConnector);
            // 将CustomRedirectHandler添加到服务器处理程序
            final HandlerList handlerList = new HandlerList();
            handlerList.addHandler(new CustomRedirectHandler());
            for(Handler handler : server.getHandlers()) {
                handlerList.addHandler(handler);
            }
            server.setHandler(handlerList);
        }
    });
    return factory;
}

在我们的"CustomRedirectHandler"中,我们可以检查请求的端点是否在我们的"allowed http"数组中。如果它已经请求了https,或者允许使用http,则不做任何操作,否则重定向到https。我的示例只允许针对以"/.well-known/acme-challenge/"开头的端点使用http,以允许对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) {
            // 已经请求了https,无需处理
            return;
        }
        // 检查请求是否允许使用http
        if (allowHttp(baseRequest)) {
            return;
        }
        // 否则重定向到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;
    }
}

<details>
<summary>英文:</summary>

I figured this out for **Jetty** servlet which I use. If you use the default TomCat servlet you will have to do something similar that works for TomCat I suppose.

So to start with I have a ssl port as default that is activated. To also allow http you need to configure an additional http port in your config. Then you need to add a server Handler. You could add the Handler SecuredRedirectHandler to redirect ALL http requests to the https port. Since we don&#39;t want to redirect ALL http requests we make our own CustomRedirectHandler that extends 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;
    }

In our CustomRedirectHandler we can check if the requested endpoint is in our &quot;allowed http&quot; array. If it already request https or is allowed http then we do nothing, else redirect to https. My example allows http only for the endpoint that starts with &quot;/.well-known/acme-challenge/&quot; to allow requests to http://example.com/.well-known/acme-challenge/TOKEN for example.

    public class CustomRedirectHandler extends SecuredRedirectHandler {
    	
    	private final String[] allowedHttp = {&quot;/.well-known/acme-challenge/&quot;};
    	
    	@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;
    	}
    	
    	
    }



</details>



huangapple
  • 本文由 发表于 2020年10月19日 23:34:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/64430554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定