如何配置Spring应用仅响应指定域名的请求?
解决方案:Spring应用仅响应指定域名请求(无反向代理)
针对你的需求,直接在Spring应用内部实现请求域名校验,无需依赖反向代理,同时支持动态配置允许的域名,具体方案如下:
方案一:自定义Spring MVC拦截器
通过拦截所有请求,校验请求头中的Host字段是否匹配配置的允许域名,不匹配则直接返回403禁止访问。
1. 配置允许的域名
在application.properties(或application.yml)中添加配置:
# 允许访问的域名,支持命令行参数覆盖:--allowed.domain=your-custom-domain.example.com allowed.domain=myservice.example.com
2. 创建请求拦截器
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @Component public class DomainValidationInterceptor implements HandlerInterceptor { @Value("${allowed.domain}") private String allowedDomain; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestHost = request.getHeader("Host"); // 移除端口(如果有的话),只校验域名部分 if (requestHost != null) { requestHost = requestHost.split(":")[0]; } // 校验Host是否匹配允许的域名 if (allowedDomain.equals(requestHost)) { return true; } // 不匹配则返回403 response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write("Access Denied: Invalid Domain"); return false; } }
3. 注册拦截器
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { private final DomainValidationInterceptor domainValidationInterceptor; @Autowired public WebConfig(DomainValidationInterceptor domainValidationInterceptor) { this.domainValidationInterceptor = domainValidationInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { // 对所有请求生效 registry.addInterceptor(domainValidationInterceptor).addPathPatterns("/**"); } }
方案二:利用Spring Security实现(适合已集成Security的场景)
如果你的应用已经使用Spring Security,可以通过自定义请求匹配器来限制域名:
1. 配置允许的域名(同方案一)
allowed.domain=myservice.example.com
2. 配置Security规则
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.RequestMatcher; import jakarta.servlet.http.HttpServletRequest; @Configuration @EnableWebSecurity public class SecurityConfig { @Value("${allowed.domain}") private String allowedDomain; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(auth -> auth // 仅允许指定域名的请求访问所有接口 .requestMatchers(allowedDomainMatcher()).permitAll() // 其他所有请求拒绝访问 .anyRequest().denyAll() ); return http.build(); } private RequestMatcher allowedDomainMatcher() { return new RequestMatcher() { @Override public boolean matches(HttpServletRequest request) { String requestHost = request.getHeader("Host"); if (requestHost != null) { requestHost = requestHost.split(":")[0]; } return allowedDomain.equals(requestHost); } }; } }
额外优化:禁止IP直接访问
如果需要彻底禁止通过IP(如198.51.100.1:8080)访问,可在拦截逻辑中添加判断:
// 在preHandle方法中添加 if (requestHost != null && requestHost.matches("\\d+\\.\\d+\\.\\d+\\.\\d+")) { response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write("Access Denied: IP Access Not Allowed"); return false; }
动态配置说明
- 部署时可通过命令行参数覆盖域名配置:
java -jar your-app.jar --allowed.domain=custom-service.example.com --server.port=8080 - 多机器部署时,只需在每台机器的启动命令或配置文件中设置对应的
allowed.domain即可。
内容的提问来源于stack exchange,提问作者HukuToc2288
相关产品推荐
相关产品推荐

