栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

redis防止黑客恶意攻击的简单办法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

redis防止黑客恶意攻击的简单办法

1.在redis中放入有用户标识的key,每次用户操作时都会根据用户标识的key去匹配一下,匹配上就能操作,匹配不上就拒绝。

下面的代码是商品秒杀场景,根据用户id和商品id去生成一个标识,然后放入redis缓存中。

@Override
    public String getMd5(Integer id,Integer userid){
        //检验用户的合法性
        User user = userMapper.findById(userid);
        if(user == null) throw new RuntimeException("用户信息不存在!");
        log.info("用户信息:[{}]",user.toString());
        //检验商品的合法性
        Stock stock = stockMapper.checkStock(id);
        if(stock == null) throw new RuntimeException("商品信息不合法!");
        log.info("商品信息:[{}]",stock.toString());
        //生成hashkey
        String hashKey = "KEY_"+userid+"_"+id;
        //生成md5//这里!QS#是一个盐 随机生成
        String key = DigestUtils.md5DigestAsHex((userid+id+"!Q*jS#").getBytes());
        stringRedisTemplate.opsForValue().set(hashKey,key,3600, TimeUnit.SECONDS);
        log.info("Redis写入:[{}][{}]",hashKey,key);
        return key;
    }

用户要秒杀商品时,根据用户id和商品id去redis查找有没有对应的签名,如果有则放行,没有就抛出异常。

 @Override
    public int kill(Integer id, Integer userid, String md5) {
        //校验redis中秒杀商品是否超时
        if(!stringRedisTemplate.hasKey("killphone")){
            throw new RuntimeException("当前商品的抢购活动已经结束啦~~");
        }
        //先验证签名
        String hashKey = "KEY_"+userid+"_"+id;
        String s = stringRedisTemplate.opsForValue().get(hashKey);
        if(s==null) 
        	throw new RuntimeException("没有携带验证签名,请求不合法!");
        if(!s.equals(md5))
            throw new RuntimeException("当前请求数据不合法,请稍后再试!");
        //校验库存
        Stock stock = checkStock(id);
        //更新库存
        updateSale(stock);
        //创建订单
        return createOrder(stock);
    }
2.用redis根据用户id在一定时间范围内统计用户访问次数,超过一定次数就限制访问。

下面这个类是在redis中保存和查询用户访问次数。

@Slf4j
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public int saveUserCount(Integer userId) {
         //根据不同用户id生成调用次数的key
        String limitKey = "LIMIT"+"_"+userId;
        //获取redis中指定key的调用次数
        String limitNum = stringRedisTemplate.opsForValue().get(limitKey);
        int limit = -1;
        if(limitNum == null){
            //第一次调用放入redis中设置为0
            stringRedisTemplate.opsForValue().set(limitKey,"0",3600, TimeUnit.SECONDS);
         }else{
            //不是第一次调用每次+1
            limit = Integer.parseInt(limitNum)+1;
            stringRedisTemplate.opsForValue().set(limitKey,String.valueOf(limit),3600,TimeUnit.SECONDS);
        }
        return limit;
    }

    @Override
    public boolean getUserCount(Integer userId) {
        //根据userid对应key获取调用次数
        String limitKey = "LIMIT"+"_"+userId;
        //根据用户调用次数的key获取redis中调用次数
        String limitNum = stringRedisTemplate.opsForValue().get(limitKey);
        if(limitNum == null){
            //为空直接抛弃说明key出现异常
            log.error("该用户没有访问申请验证值记录,疑似异常");
            return true;
        }
        return Integer.parseInt(limitNum) > 10;//false代表没有超过,true代表超过
    }
}

当用户在一定时间内访问次数达到限制次数,就不让用户再去访问了。

//开发一个秒杀方法 乐观锁防止超卖+令牌桶算法限流+md5签名(hash接口隐藏)+单用户访问频率限制
    @GetMapping("killtokenmd5limit")
    public String killtokenmd5limit(Integer id,Integer userid,String md5){
        System.out.println("秒杀商品的id="+id);
        //加入 令牌桶的限流措施
        if(!rateLimiter.tryAcquire(3, TimeUnit.SECONDS)){
            log.info("抛弃请求:抢购失败,当前秒杀活动过于火爆,请重试");
            return "抛弃请求:抢购失败,当前秒杀活动过于火爆,请重试!";
        }
        try{
            //单用户调用接口的频率限制
            int count = userService.saveUserCount(userid);
            log.info("用户截止该次的访问次数为:[{}]",count);
            //进行调用次数的判断
            boolean isBanned = userService.getUserCount(userid);
            if(isBanned){
                log.info("购买失败,超过频率限制!");
                return "购买失败,超过频率限制!";
            }
            //根据秒杀商品id 去调用秒杀业务
            int orderId = orderService.kill(id,userid,md5);
            return "秒杀成功,订单id为:"+String.valueOf(orderId);
        }catch(Exception e){
            e.printStackTrace();
            return e.getMessage();
        }
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/685747.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号