Spring WebFlux:将HTTP重定向到HTTPS

8
我该如何在Spring Webflux中配置http->https重定向? 我需要所有的http请求都被重定向到https(据我所知,任何http请求都应该有301 http状态响应,改变http->https)。 在文档中没有找到相关信息。 我找到了这个答案,但它与Tomcat相关,而我使用的是Netty。

在那个答案中有不同的回答。你试过 https://dev59.com/OV8d5IYBdhLWcg3wlzD6#38829838 吗? - pvpkiran
感谢@pvpkiran的评论,我使用默认端口8080,并且我也没有配置安全性(在这个项目中不需要安全性)。类路径中没有WebSecurityConfigurerAdapter - Zufar Muhamadeev
3个回答

14

我找到了一种方法,希望能帮助到有需要的人:

@Bean
public WebFilter httpsRedirectFilter() {
    return new WebFilter() {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
            URI originalUri = exchange.getRequest().getURI();

            //here set your condition to http->https redirect
            List<String> forwardedValues = exchange.getRequest().getHeaders().get("x-forwarded-proto");
            if (forwardedValues != null && forwardedValues.contains("http")) {
                try {
                    URI mutatedUri = new URI("https",
                            originalUri.getUserInfo(),
                            originalUri.getHost(),
                            originalUri.getPort(),
                            originalUri.getPath(),
                            originalUri.getQuery(),
                            originalUri.getFragment());
                    ServerHttpResponse response = exchange.getResponse();
                    response.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
                    response.getHeaders().setLocation(mutatedUri);
                    return Mono.empty();
                } catch (URISyntaxException e) {
                    throw new IllegalStateException(e.getMessage(), e);
                }
            }
            return chain.filter(exchange);
        }
    };
}

但是如何指定HTTP端口呢?因为在yml文件中只提到了HTTPS端口。server.port: 8443 - Arpan Das
@ArpanDas 这是针对已经有https终止代理的情况(在我的情况下是gcloud kubernetes Ingress)。如果您的客户端使用“http”模式的URL访问后端,则可以使用此过滤器将其重定向到“https”。 - Zufar Muhamadeev

5

我使用以下方式使其工作。然而,我怀疑这种方式得不到支持,并且可能在未来引起问题。

@Configuration
public class HttpToHttpsRedirectConfig {

    @PostConstruct
    public void startRedirectServer() {
        NettyReactiveWebServerFactory httpNettyReactiveWebServerFactory = new NettyReactiveWebServerFactory(8080);
        httpNettyReactiveWebServerFactory.getWebServer((request, response) -> {
            URI uri = request.getURI();
            URI httpsUri;
            try {
                httpsUri = new URI("https", uri.getUserInfo(), uri.getHost(), 8443, uri.getPath(), uri.getQuery(), uri.getFragment());
            } catch (URISyntaxException e) {
                return Mono.error(e);
            }
            response.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
            response.getHeaders().setLocation(httpsUri);
            return response.setComplete();
        }).start();
    }

}

我建议在条件属性上执行此操作,例如 @ConditionalOnProperty(value="server.port", havingValue = "443") - Luke Kroon

0

有一个内置的redirectToHttps过滤器对我很有用。它可以按照以下方式使用:

@Bean
public SecurityWebFilterChain securityWebFilterChain(final ServerHttpSecurity http) {
    http
        .authorizeExchange()
            .anyExchange()
                .authenticated()
                .and().oauth2Login()
        .redirectToHttps();

    return http.build();
}

文档可以在这里找到


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接