Spring Boot配置:Web界面走HTTPS、Web服务走HTTP
问题:Spring Boot 实现Web界面与Web服务分协议(HTTPS/HTTP)配置
我是Spring Boot新手,对Spring基础内容尚未完全掌握。我的应用同时提供一组Web服务和一个用于展示数据的Web界面,目前面临配置难题:需要让Web界面和Web服务分别使用HTTPS和HTTP协议(因Web服务客户端目前仅支持HTTP,后续会升级)。
当前配置情况
- Web界面(UI)端点:
localhost:port/web/** - Web服务(API)端点:
localhost:port/ws/**
目前整个应用(含界面和服务)以HTTP运行时可正常工作,但无法实现分协议配置。
当前安全配置代码
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // Disable LDAP login for All endpoint web services (/ws/**) http .requiresChannel(channelConfigurer -> channelConfigurer.anyRequest().requiresInsecure()) .authorizeHttpRequests(request -> request.requestMatchers(new AntPathRequestMatcher("/ws/**")) .permitAll()); // Enforce LDAP login for the web management interface (/web/**) http .requiresChannel(channelConfigurer -> channelConfigurer.anyRequest().requiresSecure()) .authorizeHttpRequests(request -> request.requestMatchers(new AntPathRequestMatcher("/web/**")) .authenticated().anyRequest().fullyAuthenticated()) .formLogin(Customizer.withDefaults()); http.csrf(AbstractHttpConfigurer::disable); return http.build(); }
已尝试但未成功的方案
- 配置应用使用HTTPS,但会影响整个应用,无法实现分离;
- 尝试仅对Web界面端点
localhost:port/web/**强制使用HTTPS,但未生效。对应的尝试代码如下:
@Bean public SecurityFilterChain secureSecurityFilterChain(HttpSecurity httpSecurity) throws Exception { // Configure the security filter chain for secure (HTTPS) requests. return httpSecurity.securityMatcher("/web/**") .requiresChannel(channelConfigure -> channelConfigure .requestMatchers(ServletRequest::isSecure) //.requiresInsecure() // Require HTTP //.requiresSecure() // Require HTTPS ) .authorizeHttpRequests(authorizeRequests -> authorizeRequests .anyRequest().permitAll() // Allow all secure requests ) .build(); }
解决方案
要实现Web界面(/web/**)强制HTTPS、Web服务(/ws/**)强制HTTP的需求,需分两步配置:先让Spring Boot同时监听HTTP和HTTPS端口,再通过多个SecurityFilterChain分别对不同路径设置协议要求和权限规则。
步骤1:配置Spring Boot同时支持HTTP和HTTPS端口
在application.properties中添加以下配置:
# HTTPS配置(用于Web界面) server.port=8443 server.ssl.key-store=classpath:your-keystore.jks server.ssl.key-store-password=your-password server.ssl.key-alias=your-alias # HTTP配置(用于Web服务) server.http.port=8080
若使用YAML格式:
server: port: 8443 ssl: key-store: classpath:your-keystore.jks key-store-password: your-password key-alias: your-alias http: port: 8080
然后添加配置类注册HTTP连接器:
@Configuration public class ServerConfig { @Value("${server.http.port}") 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); return connector; } }
步骤2:配置多个SecurityFilterChain分别处理不同路径
创建两个SecurityFilterChain,分别匹配对应路径并设置规则:
1. 处理Web服务(/ws/**)的FilterChain:强制HTTP、无需登录
@Bean @Order(1) // 优先级更高,优先匹配/ws/**路径 public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception { http .securityMatcher("/ws/**") .requiresChannel(channel -> channel .anyRequest().requiresInsecure() // 强制使用HTTP ) .authorizeHttpRequests(auth -> auth .anyRequest().permitAll() // 所有/ws/**请求无需认证 ) .csrf(csrf -> csrf.disable()); return http.build(); }
2. 处理Web界面(/web/**)的FilterChain:强制HTTPS、需要LDAP登录
@Bean @Order(2) public SecurityFilterChain uiSecurityFilterChain(HttpSecurity http) throws Exception { http .securityMatcher("/web/**") .requiresChannel(channel -> channel .anyRequest().requiresSecure() // 强制使用HTTPS ) .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() // 所有/web/**请求需要认证 ) .formLogin(Customizer.withDefaults()) // 使用默认表单登录(LDAP需额外配置) .csrf(csrf -> csrf.disable()); return http.build(); }
关键说明
@Order注解:必须为不同的SecurityFilterChain设置优先级,Spring会按顺序匹配请求,优先级高的先处理。securityMatcher:每个FilterChain仅处理匹配的路径,避免规则冲突。- 原代码问题:单个FilterChain中重复调用
requiresChannel会导致后设置的规则覆盖前者;尝试的第二个FilterChain未启用requiresSecure配置,因此未生效。
内容的提问来源于stack exchange,提问作者qsf
相关产品推荐
相关产品推荐

