You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot REST Controller:如何为不同端点分别启用HTTP与HTTPS

实现Spring Boot部分端点HTTP、部分HTTPS的方案

你遇到的问题很典型——只配置双连接器会让所有端点同时暴露在两种协议下,核心是要给不同路径加上协议访问限制。下面给你两种靠谱的实现方式,按需选择:

方式一:用Spring Security(推荐,更规范)

如果你的项目已经在用Spring Security,或者愿意引入它,这是最简洁的方案。通过Security规则直接指定不同路径必须使用的协议:

步骤1:先配置双端口(HTTP + HTTPS)

首先确保两个连接器正常工作:

  • application.properties里配置HTTPS:
server.port=8443
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=yourpassword
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=youralias
  • 编程方式添加HTTP连接器(比如8080端口):
@Configuration
public class ServerConfig {

    @Value("${server.http.port:8080}")
    private int httpPort;

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(createHttpConnector());
        return tomcat;
    }

    private Connector createHttpConnector() {
        Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setPort(httpPort);
        // 这里暂不配置全局重定向,后续用Security控制路径级别的协议规则
        return connector;
    }
}

步骤2:配置Security的协议规则

创建Security配置类,对不同路径指定协议要求:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().permitAll() // 根据你的实际权限需求调整,这里先允许所有请求
            )
            .requiresChannel(channel -> channel
                // 指定哪些路径必须用HTTPS
                .requestMatchers("/api/secure/**").requiresSecure()
                // 指定哪些路径仅允许HTTP
                .requestMatchers("/api/public/**").requiresInsecure()
                // 其他路径默认强制HTTPS(可按需修改)
                .anyRequest().requiresSecure()
            );
        return http.build();
    }
}

这样一来,访问/api/secure/**的HTTP请求会自动重定向到HTTPS;访问/api/public/**的HTTPS请求会重定向到HTTP,完全符合你的需求。

方式二:自定义Filter(无需Spring Security)

如果不想引入Spring Security,可以写一个自定义过滤器,在请求到达端点前校验协议是否匹配:

步骤1:同样先配置双端口(和方式一的步骤1一致)

步骤2:编写协议校验Filter

@Component
public class ProtocolValidationFilter implements Filter {

    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
    // 定义需要HTTPS的路径
    private static final List<String> HTTPS_REQUIRED_PATHS = Arrays.asList("/api/secure/**");
    // 定义仅允许HTTP的路径
    private static final List<String> HTTP_ALLOWED_PATHS = Arrays.asList("/api/public/**");

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String requestURI = httpRequest.getRequestURI();
        boolean isSecure = httpRequest.isSecure();

        // 检查是否是需HTTPS的路径
        boolean requiresHttps = HTTPS_REQUIRED_PATHS.stream().anyMatch(path -> PATH_MATCHER.match(path, requestURI));
        // 检查是否是仅允许HTTP的路径
        boolean requiresHttp = HTTP_ALLOWED_PATHS.stream().anyMatch(path -> PATH_MATCHER.match(path, requestURI));

        if (requiresHttps && !isSecure) {
            // 重定向到HTTPS,或返回403错误(按需选择)
            String httpsUrl = "https://" + httpRequest.getServerName() + ":8443" + requestURI;
            httpResponse.sendRedirect(httpsUrl);
            return;
        }

        if (requiresHttp && isSecure) {
            // 重定向到HTTP,或返回403错误(按需选择)
            String httpUrl = "http://" + httpRequest.getServerName() + ":8080" + requestURI;
            httpResponse.sendRedirect(httpUrl);
            return;
        }

        // 协议符合要求,继续执行后续逻辑
        chain.doFilter(request, response);
    }
}

这个过滤器会在每个请求到达时校验路径与协议的匹配性,不匹配则重定向到正确协议的端口,也可以根据业务需求改成直接返回403 Forbidden错误。

关键注意点

  • 重定向时要确保端口配置正确(HTTPS端口对应application.properties中的配置,HTTP端口对应编程添加的端口)。
  • 测试时分别用两个端口访问不同路径,确认拦截/重定向逻辑是否生效。
  • 若项目有其他过滤器,注意调整该协议校验Filter的执行顺序,尽量放在最前面。

内容的提问来源于stack exchange,提问作者Omkar

火山引擎 最新活动