You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用SpringWebFilterChain对特定主机进行身份验证

基于请求主机匹配的Spring WebFlux Security配置

当前可通过路径模式过滤或验证请求,但需根据请求主机进行匹配。示例URL为http://localhost:8080/path,请求结构如下:

SchemeHostPath
http://localhost:8080/demo

目前匹配路径模式(如/get)的方法如下:

.pathMatchers(autPatterns).permitAll()
.pathMatchers(securePatterns).authenticated()

Spring Security没有直接提供匹配请求主机的方法,需自定义ServerWebExchangeMatcher实现,目标是达成类似.anyExchange(exch -> matcherForHost).authenticated()的逻辑。

解决方案

修改SecurityConfig,添加自定义主机匹配器并集成到授权规则中:

package org.demo;

import java.security.Key;
import java.util.List;
import java.util.regex.Pattern;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import reactor.core.publisher.Mono;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    // 创建主机匹配器:匹配指定正则的请求主机
    private ServerWebExchangeMatcher createHostMatcher(List<String> secureHostPatterns) {
        List<Pattern> patterns = secureHostPatterns.stream()
                .map(Pattern::compile)
                .toList();
        
        return exchange -> {
            String host = exchange.getRequest().getHeaders().getFirst("Host");
            if (host == null) {
                return Mono.just(ServerWebExchangeMatcher.MatchResult.notMatch());
            }
            boolean matches = patterns.stream().anyMatch(p -> p.matcher(host).matches());
            return matches ? Mono.just(ServerWebExchangeMatcher.MatchResult.match()) 
                           : Mono.just(ServerWebExchangeMatcher.MatchResult.notMatch());
        };
    }

    @Bean
    SecurityWebFilterChain springWebFilterChain(@Autowired ServerHttpSecurity http, 
                                               @Autowired AuthenticationManager authenticationManager, 
                                               @Autowired SecurityContextRepository securityContextRepository) {
        String[] autPatterns = new String[]{"/demo/auth/**"};
        String[] securePatterns = new String[]{"/demo/**"};
        List<String> secureHosts = List.of(".*localhost.*", ".*local\\.com.*");

        // 初始化自定义主机匹配器
        ServerWebExchangeMatcher hostMatcher = createHostMatcher(secureHosts);

        return http.cors().disable()
                .exceptionHandling()
                .authenticationEntryPoint((s, e) -> Mono.fromRunnable(() ->
                        s.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED)
                )).accessDeniedHandler((s, e) -> Mono.fromRunnable(() ->
                        s.getResponse().setStatusCode(HttpStatus.FORBIDDEN)
                )).and()
                .csrf().disable()
                .authenticationManager(authenticationManager)
                .securityContextRepository(securityContextRepository)
                .authorizeExchange()
                .pathMatchers(autPatterns).permitAll()
                // 组合规则:匹配指定路径且主机在列表中的请求需要认证
                .pathMatchers(securePatterns).matchers(hostMatcher).authenticated()
                // 其余请求允许访问
                .anyExchange().permitAll()
                .and()
                .build();
    }
}

关键说明

  • createHostMatcher方法:将传入的主机正则列表编译为Pattern,校验请求的Host头是否匹配任意正则,返回匹配结果。
  • 授权规则中使用.pathMatchers(securePatterns).matchers(hostMatcher).authenticated(),实现路径+主机的组合校验,仅同时满足两个条件的请求需要认证。
  • 若需单独基于主机匹配(不结合路径),可直接使用.matchers(hostMatcher).authenticated()替代路径匹配规则。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 10:05:18