>  기사  >  Java  >  Spring Boot가 악의적인 인터페이스 새로 고침 및 무차별 대입 요청을 방지하는 방법

Spring Boot가 악의적인 인터페이스 새로 고침 및 무차별 대입 요청을 방지하는 방법

WBOY
WBOY앞으로
2023-05-12 22:19:041405검색

먼저 핵심 코드이기도 한 사용자 정의 인터셉터 클래스를 만듭니다.

/**
 * @package: com.technicalinterest.group.interceptor
 * @className: IpUrlLimitInterceptor
 * @description: ip+url重复请求现在拦截器
 * @author: Shuyu.Wang
 * @date: 2019-10-12 12:34
 * @since: 0.1
 **/
@Slf4j
public class IpUrlLimitInterceptor implements HandlerInterceptor {
 
 
    private RedisUtil getRedisUtil() {
        return  SpringContextUtil.getBean(RedisUtil.class);
    }
 
    private static final String LOCK_IP_URL_KEY="lock_ip_";
 
    private static final String IP_URL_REQ_TIME="ip_url_times_";
 
    private static final long LIMIT_TIMES=5;
 
    private static final int IP_LOCK_TIME=60;
 
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        log.info("request请求地址uri={},ip={}", httpServletRequest.getRequestURI(), IpAdrressUtil.getIpAdrress(httpServletRequest));
        if (ipIsLock(IpAdrressUtil.getIpAdrress(httpServletRequest))){
            log.info("ip访问被禁止={}",IpAdrressUtil.getIpAdrress(httpServletRequest));
            ApiResult result = new ApiResult(ResultEnum.LOCK_IP);
            returnJson(httpServletResponse, JSON.toJSONString(result));
            return false;
        }
        if(!addRequestTime(IpAdrressUtil.getIpAdrress(httpServletRequest),httpServletRequest.getRequestURI())){
            ApiResult result = new ApiResult(ResultEnum.LOCK_IP);
            returnJson(httpServletResponse, JSON.toJSONString(result));
            return false;
        }
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
 
    }
 
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
 
    }
 
    /**
     * @Description: 判断ip是否被禁用
     * @author: shuyu.wang
     * @date: 2019-10-12 13:08
     * @param ip
     * @return java.lang.Boolean
     */
    private Boolean ipIsLock(String ip){
        RedisUtil redisUtil=getRedisUtil();
        if(redisUtil.hasKey(LOCK_IP_URL_KEY+ip)){
            return true;
        }
        return false;
    }
    /**
     * @Description: 记录请求次数
     * @author: shuyu.wang
     * @date: 2019-10-12 17:18
     * @param ip
     * @param uri
     * @return java.lang.Boolean
     */
    private Boolean addRequestTime(String ip,String uri){
        String key=IP_URL_REQ_TIME+ip+uri;
        RedisUtil redisUtil=getRedisUtil();
        if (redisUtil.hasKey(key)){
            long time=redisUtil.incr(key,(long)1);
            if (time>=LIMIT_TIMES){
                redisUtil.getLock(LOCK_IP_URL_KEY+ip,ip,IP_LOCK_TIME);
                return false;
            }
        }else {
            redisUtil.getLock(key,(long)1,1);
        }
        return true;
    }
 
    private void returnJson(HttpServletResponse response, String json) throws Exception {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/json; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(json);
        } catch (IOException e) {
            log.error("LoginInterceptor response error ---> {}", e.getMessage(), e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
 
 
}

코드의 Redis는 스레드 안전성과 기능 구현을 최대한 보장할 수 있는 분산 잠금을 사용합니다. 코드에 설정된 내용은 1S 내에서 동일한 IP를 통해 동일한 인터페이스에 5번 액세스하면 해당 IP가 1시간 동안 비활성화된다는 것입니다. 원하는 기능을 달성하기 위해 프로젝트 요구 사항에 따라 적절하게 수정할 수 있습니다.

redis 분산 잠금 키 코드:

/**
 * @package: com.shuyu.blog.util
 * @className: RedisUtil
 * @description:
 * @author: Shuyu.Wang
 * @date: 2019-07-14 14:42
 * @since: 0.1
 **/
@Component
@Slf4j
public class RedisUtil {
 
    private static final Long SUCCESS = 1L;
 
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // =============================common============================
 
    
 
    /**
     * 获取锁
     * @param lockKey
     * @param value
     * @param expireTime:单位-秒
     * @return
     */
    public boolean getLock(String lockKey, Object value, int expireTime) {
        try {
            log.info("添加分布式锁key={},expireTime={}",lockKey,expireTime);
            String script = "if redis.call(&#39;setNx&#39;,KEYS[1],ARGV[1]) then if redis.call(&#39;get&#39;,KEYS[1])==ARGV[1] then return redis.call(&#39;expire&#39;,KEYS[1],ARGV[2]) else return 0 end end";
            RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
            Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value, expireTime);
            if (SUCCESS.equals(result)) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
 
    /**
     * 释放锁
     * @param lockKey
     * @param value
     * @return
     */
    public boolean releaseLock(String lockKey, String value) {
        String script = "if redis.call(&#39;get&#39;, KEYS[1]) == ARGV[1] then return redis.call(&#39;del&#39;, KEYS[1]) else return 0 end";
        RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
        Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
        if (SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }
 
}

마지막으로, Registry.addInterceptor를 통해 위의 사용자 정의 인터셉터를 추가하면 적용됩니다.

위 내용은 Spring Boot가 악의적인 인터페이스 새로 고침 및 무차별 대입 요청을 방지하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제