API安全(三)-流控

1、什么是流控

  所谓流控,就是流量控制,也称作限流。只放系统能够处理的请求数量过去。

2、为什么要做流控

  保证系统的可用性,防止大流量把系统压死。如果系统不可用。其实做什么都没有意义了。还以用作安全目的,比如可以减慢暴力密码破解的速率。还可以用来抵御DDOS攻击。

3、流控为什么要在整个安全机制链路的第一关

  因为认证、审计,授权都是需要消耗系统资源的。能够越早把一些请求拒绝掉,资源的浪费就会越少。就能处理更多的请求。所以流控应该是在整个安全机制的最前面。且就算后面的安全机制做的再好,服务器被大流量压死了,服务不可用也没用了。

  

4、流控可以在什么地方做

  4.1、在负载均衡、反向代理上做,一般是针对整个集群来做的。比如说在nginx上,和网关上(zuul)等。

  4.2、在自己的应用中,针对单个应用节点。

  可以的话,在两端都进行配置。

  nginx上做流控限制:https://www.nginx.com/blog/rate-limiting-nginx/

5、使用Guava做简单的流量控制

  5.1、导入guava依赖

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.0-jre</version>
        </dependency>

  5.2、编写过滤器

/**
 * 流控过滤器
 * 继承OncePerRequestFilter,保证一次请求只执行一次该过滤器
 *
 * @author caofanqi
 * @date 2020/1/20 23:29
 */
@Component
@SuppressWarnings("ALL")
public class RateLimiterFilter extends OncePerRequestFilter {

    /**
     * 限制每秒只允许一个请求
     */
    private RateLimiter rateLimiter = RateLimiter.create(1);


    @Override
    protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if(rateLimiter.tryAcquire()) {
            filterChain.doFilter(request, response);
        }else {
            /*
             * 请求过Http状态码返回429
             */
            response.setContentType(MediaType.TEXT_HTML_VALUE);
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.getWriter().write("Too Many Requests");
            response.getWriter().flush();
        }

    }

}

  5.3、启动服务,访问http://127.0.0.1:9090/users/1 进行快速发送请求测试

  

  当然在实际的开发中,我们所要面对的流控的场景是非常复杂的,不是简单的设个数就完了。比如说会根据用户来限流,可能需要把更多的资源留给vip用户,那么vip用户可能是每秒500请求,普通用户可能是每秒50请求。这样的话,当大量的请求过来之后,vip用户能正常使用网站,普通用户可能会有很多请求就被拒绝掉了。

  Guava的RateLimiter类参考文档:http://ifeve.com/guava-ratelimiter/

 

源码路径:https://github.com/caofanqi/study-security/tree/dev-rate-limiter

猜你喜欢

转载自www.cnblogs.com/caofanqi/p/12221309.html