package com.doumee.core.annotation.pr; 
 | 
  
 | 
import com.doumee.service.proxy.CacheProxy; 
 | 
import lombok.Data; 
 | 
import org.springframework.beans.factory.annotation.Autowired; 
 | 
  
 | 
import javax.servlet.http.HttpServletRequest; 
 | 
import java.io.Serializable; 
 | 
  
 | 
/** 
 | 
 * 防重复提交实现接口 
 | 
 * @author Eva.Caesar Liu 
 | 
 * @date 2023/03/21 14:49 
 | 
 */ 
 | 
public abstract class PreventRepeatAdapter { 
 | 
  
 | 
    // 请求Key前缀 
 | 
    private static final String REQUEST_KEY_PREFIX = "eva:pr:"; 
 | 
  
 | 
    // 暴力请求Key前缀 
 | 
    private static final String MASSIVE_KEY_PREFIX = "eva:massive:"; 
 | 
  
 | 
    @Autowired 
 | 
    private CacheProxy<String, Object> cacheProxy; 
 | 
  
 | 
    /** 
 | 
     * 验证是否重复 
 | 
     */ 
 | 
    public Boolean prevent(HttpServletRequest request, int interval) { 
 | 
        String requestKey = REQUEST_KEY_PREFIX + this.sign(request); 
 | 
        boolean isRepeat = cacheProxy.get(requestKey) != null; 
 | 
        if (!isRepeat) { 
 | 
            cacheProxy.put(requestKey, System.currentTimeMillis(), Long.valueOf(interval)); 
 | 
        } 
 | 
        return isRepeat; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 验证是否暴力涌入 
 | 
     */ 
 | 
    public Boolean massive (HttpServletRequest request, int maxFreq, int lockTime) { 
 | 
        String massiveKey = MASSIVE_KEY_PREFIX + this.sign(request); 
 | 
        Object unit = cacheProxy.get(massiveKey); 
 | 
        if (unit == null) { 
 | 
            cacheProxy.put(massiveKey, new MassiveUnit(maxFreq, lockTime), 60); 
 | 
            return Boolean.FALSE; 
 | 
        } 
 | 
        MassiveUnit massiveUnit = (MassiveUnit) unit; 
 | 
        if (massiveUnit.getLock() == 1) { 
 | 
            return Boolean.TRUE; 
 | 
        } 
 | 
        if (massiveUnit.getFreq() >= massiveUnit.getMaxFreq()) { 
 | 
            massiveUnit.setLock((byte)1); 
 | 
            cacheProxy.put(massiveKey, massiveUnit, Long.valueOf(massiveUnit.getLockTime())); 
 | 
            return Boolean.TRUE; 
 | 
        } 
 | 
        massiveUnit.increment(); 
 | 
        cacheProxy.put(massiveKey, massiveUnit); 
 | 
        return Boolean.FALSE; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 参数签名 
 | 
     */ 
 | 
    public abstract String sign (HttpServletRequest request); 
 | 
  
 | 
    /** 
 | 
     * 暴力验证单元 
 | 
     */ 
 | 
    @Data 
 | 
    static class MassiveUnit implements Serializable { 
 | 
  
 | 
        private byte lock = 0; 
 | 
  
 | 
        // 请求频率 
 | 
        private int freq = 1; 
 | 
  
 | 
        // 最高频率 
 | 
        private int maxFreq; 
 | 
  
 | 
        // 锁定时长 
 | 
        private int lockTime; 
 | 
  
 | 
        MassiveUnit (int maxFreq, int lockTime) { 
 | 
            this.maxFreq = maxFreq; 
 | 
            this.lockTime = lockTime; 
 | 
        } 
 | 
  
 | 
        void increment () { 
 | 
            this.freq++; 
 | 
        } 
 | 
    } 
 | 
} 
 |