基于Spring Security添加流控的过程:
步骤1: 添加依赖
确保项目中包含了Spring Security和Sentinel-Core的相关依赖。在Maven项目中,可以在pom.xml
中添加如下依赖:
xml
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Sentinel-Core -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.6</version> <!-- 根据最新版本调整 -->
</dependency>
步骤2: 初始化Sentinel配置
创建一个配置类来初始化Sentinel,并加载流控规则。使用@Configuration
注解标记此配置类,并通过@PostConstruct
注解的方法来确保在应用启动时执行初始化逻辑。
java
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class SentinelConfig implements InitFunc {
@Override
public void init() throws Exception {
loadFlowRules();
}
@PostConstruct
public void loadFlowRules() {
List<FlowRule> rules = new ArrayList<>();
// 通用限流规则
FlowRule generalRule = new FlowRule("/*")
.setCount(100) // 一般接口的限流阈值
.setGrade(FlowRule.Grade.QPS)
.setControlBehavior(FlowRule.ControlBehavior.DEFAULT);
rules.add(generalRule);
// 白名单URL的特殊流控规则,假设允许较高流量
FlowRule whitelistRule = new FlowRule("/api/public/**")
.setCount(1000) // 较宽松的限流阈值
.setGrade(FlowRule.Grade.QPS)
.setControlBehavior(FlowRule.ControlBehavior.DEFAULT);
rules.add(whitelistRule);
FlowRuleManager.loadRules(rules);
}
}
步骤3: 创建Sentinel过滤器
创建一个自定义过滤器,用于在请求处理前执行Sentinel的流量控制检查。
java
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SentinelSecurityFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String uri = request.getRequestURI();
// 使用Sentinel进行流量控制检查
Entry entry = null;
try {
entry = SphU.entry(uri);
filterChain.doFilter(request, response);
} catch (BlockException e) {
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
response.getWriter().write("Too many requests.");
} finally {
if (entry != null) {
entry.exit();
}
}
}
}
步骤4: 集成到Spring Security
在Spring Security的配置中注册Sentinel过滤器,并配置安全规则。假设您已经有了一个Spring Security的配置类,如果没有,创建一个。
java
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;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SentinelSecurityFilter sentinelSecurityFilter() {
return new SentinelSecurityFilter();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // 如果不需要CSRF保护,可以关闭
.authorizeRequests(authz -> authz
.antMatchers("/api/public/**").permitAll() // 白名单URL允许匿名访问
.anyRequest().authenticated() // 其他请求需要认证
)
.addFilterBefore(sentinelSecurityFilter(), UsernamePasswordAuthenticationFilter.class) // Sentinel过滤器在JWT验证之前
.formLogin(form -> form.disable()) // 禁用表单登录,根据需要调整
.httpBasic(withDefaults()); // 或者根据需要配置HTTP Basic认证等
return http.build();
}
}
总结
- 添加依赖:引入Spring Security和Sentinel-Core的依赖。
- 配置Sentinel :通过
@Configuration
类初始化Sentinel并加载流控规则。 - 创建Sentinel过滤器:自定义过滤器实现流量控制。
- 集成Spring Security:配置类中注册过滤器并定义安全策略。
按照上述步骤,您可以基于Spring Security应用集成Sentinel-Core,实现流量控制,同时对白名单URL实施特殊处理。