文档章节

发送短信如何限制1小时内最多发送11条短信

黄威
 黄威
发布于 06/25 23:47
字数 923
阅读 44
收藏 0

发送短信如何限制1小时内最多发送11条短信

场景:
发送短信属于付费业务,有时为了防止短信攻击,需要限制发送短信的频率,例如在1个小时之内最多发送11条短信.
如何实现呢?

思路有两个

截至到当前时刻的1个小时之内,看是否有超过11条短信

Date now=new Date();
Date oneHourAgo= //1个小时之前的时刻
//查询条件有两个:时间范围,手机号
List<SMS> smsList=this.smsService.query(fromTime,toTime,mobile);
if(smsList.size()>11){
System.out.println("超出限制,禁止发送");
}else{
System.out.println("可以发送");
}

dao中:

/***
     * 获取指定时间长度(范围)内,发送的短信次数 <br />
     * 在指定时间长度(范围)内,发送的短信次数是否超出限制
     * @param startDate
     * @param endDate
     * @param mobile
     * @return
     */
    public Long count(String startDate, String endDate, String mobile) {
        CriteriaHelper criteriaHelper = CriteriaHelper.getInstance(this);
       return criteriaHelper.between("createTime",startDate,endDate)
                .eq("mobile",mobile)
                .count();
    }

Service中:

 /***
     * 在指定时间长度(范围)内,发送的短信次数是否超出限制
     * @param mobile
     * @return
     */
    public  boolean validateSMSSendCountByTimeRange(String mobile) {
        Date now=new Date();
        //1小时前的时刻
        Date oneHouseAgo = TimeHWUtil.getDateBeforeHour(now, 1);
        Long count = this.sMSDao.count(TimeHWUtil.formatDateTime(oneHouseAgo), TimeHWUtil.formatDateTime(now), mobile);
        if (count >= SMSUtil.LIMITCOUNT_SEND_SMS) {
            String msg="超出限制";
            logger.warn(msg);
            smsLogger.warn(msg);
            return false;
        }
        return true;
    }

最近的11条短信 时间跨度是否小于1小时,如果小于1小时,就禁止发送

每次发送短信,要写入当前时间戳到redis:
String mobile="13718486139"; String time=String.valueOf(DateTimeUtil.getCurrentMillisecond()); RedisHelper.getInstance().saveKeyCache("limit_one_hour", mobile+"_"+time, time);

检查时先获取所有时间戳:

Map map=RedisHelper.getInstance().getAllKeyCache("limit_one_hour"); 

具体判断逻辑:

@Test  
    public void test_limitOneHour2(){  
        String mobile="13718486139";  
        int limitCount=11;  
        int limitTime=60*60;//1小时,单位:秒  
        Map<String,String> map=new HashMap<String,String>();  
        map.put("13718486139_1445429819328", "1445431479437");  
        map.put("13718486139_1445429874699", "1445431485996");  
        map.put("13718486139_1445429874799", "1445431491527");  
        map.put("13718486139_1445430757886", "1445431496853");  
          
        System.out.println(map);  
        List<Long>list=new ArrayList<Long>();  
        for(String key:map.keySet()){  
            if(key.startsWith(mobile)){  
                list.add(Long.parseLong(map.get(key))/1000);  
            }  
        }  
        SortList<Long>sortUtil=new SortList<Long>();  
        sortUtil.Sort(list, "longValue", "desc");  
        int length=list.size();  
        int toIndex=0;//要截取的最大序号  
        if(limitCount>length){  
            toIndex=length;  
        }else{  
            toIndex=limitCount;  
        }  
        List<Long>result=list.subList(0, toIndex);  
        long delter=list.get(0).longValue()-list.get(toIndex-1).longValue();  
        long delterSecond=delter;  
        System.out.println(delterSecond);  
        if(delterSecond<limitTime){  
            System.out.println("超限");  
        }else{  
            System.out.println("可以继续发短信");  
        }  
        System.out.println(result);  
    }  

步骤:
(1)把当前手机号的所有时间戳放入list中;

(2)对list排序,按时间顺序,从大到小;(时间越大,表示离现在越近)

(3)根据次数(limitCount)限制 来截取list;

(4)计算list中第一个元素和最后一个元素的差量,即limitCount条短信的时间跨度delter

(5)若delter 小于时间限制limitTime,则表示超过限制,那么禁止发送短信

优化之后的代码:

 public static boolean isLimit() {
        long n = System.currentTimeMillis();
        Map records = RedisCacheUtil2.getPushRecordList();
        if (ValueWidget.isNullOrEmpty(records)) {
            return false;
        }
        List<String> timestamps = new ArrayList<String>(records.values());
        SortList<String> sortUtil = new SortList<String>();
        sortUtil.sort(timestamps, null, "desc");

        // 1 分钟之内不能超过 4(limitCount)
        int limitCount = 4;
        int limitTime = 60 * 1000;//1 分钟,单位:豪秒

        int length = timestamps.size();
        if (length < limitCount) {
            //没有超过限制
            return false;
        }
        int toIndex = 0;//要截取的最大序号
        /*if (limitCount + 1 > length) {
            toIndex = length;
        } else {*/
        toIndex = limitCount;
//        }
        List<String> result = timestamps.subList(0, toIndex);
        //和当前时间比较

        System.out.println("n :" + n);
        long delter = /*result.get(0))*/n - Long.parseLong(result.get(toIndex - 1));
        long delterSecond = delter;
        System.out.println("delter :" + delter);
        System.out.println(delterSecond);
        if (delterSecond < limitTime) {
            System.out.println("record :" + HWJacksonUtils.getJsonP(result));
            System.out.println("timestamps :" + HWJacksonUtils.getJsonP(timestamps));
            System.out.println("超限");
            return true;
        } else {
            System.out.println("可以继续发短信");
            return false;
        }
    }

使用限流器

参考: https://my.oschina.net/hanchao/blog/1833612
参考:http://hw1287789687.iteye.com/blog/2250898

© 著作权归作者所有

共有 人打赏支持
黄威
粉丝 16
博文 65
码字总数 35996
作品 0
昌平
程序员
私信 提问
微信小程序 - 使用阿里云发送短信

开发中使用微信小程序发送短信验证码,总结下使用的流程。 这个是首次接入完整的流程图,按照流程来基本可以实现接入。 介绍下签名和模板: 刚开始看这几个字时候会想这是啥东西?要仔细看官...

举个_栗子
05/05
0
0
运营商回应拜年短信“被重发”多扣费质疑

新华网北京2月5日电(记者张舵)春节期间,拜年短信满天飞,给全国上下带来浓浓的年味,也给一些人带来了烦恼。针对有手机用户反映“拜年短信 ‘被重发’是否会被多扣费”,中国移动和中国联通...

红薯
2011/02/07
318
0
模拟实现简易的移动用户资费统计系统

具体需求如下: 移动运营商A设置两种类型的用户:普通用户及VIP用户,现该运营商已有5个VIP用户和15个普通用户,共计20个用户。 普通用户资费标准如下(不考虑漫游和长途): 【基准资费】 ...

laodongli
2011/02/24
0
0
移动接口文档--10690

HTTP接口调用说明(支持POST和GET) HTTP网关地址: UTF8编码网关 http://api.zosms.com:6000/utf8/web_api/SendSMS_V2.aspx GBK 编码网关 http://api.zosms.com:6000/gbk/web_api/SendSMS_V2.a......

黄建清
2013/01/31
1K
2
伪基站潜伏 垃圾短信围困手机

当随处可见的小广告纸贴在一座城市的大街小巷时,作为市民,你可以不信不问;可当垃圾、违法短信不时侵入手机时,你的生活则真正地被骚扰了。 根据北京地区网站联合辟谣平台近日发布的《201...

oschina
2013/11/18
4.3K
51

没有更多内容

加载失败,请刷新页面

加载更多

GROUP BY GROUPING SETS

GROUPING SETS 子句是 SELECT 语句的 GROUP BY 子句的扩展。通过 GROUPING SETS 子句,您可采用多种方式对结果分组,而不必使用多个 SELECT 语句来实现这一目的。这就意味着,能够减少响应时...

hblt-j
12分钟前
0
0
selenium之表格的定位

真的勇士, 敢于直面惨淡的warning、 敢于正视淋漓的error 目录 被测试网页的HTML代码 1.遍历表格所有单元格 2.定位表格中的某个元素 3.定位表格中的子元素 总结 浏览器网页常常会包含各类表...

程序猿拿Q
17分钟前
0
0
adb命令启动展讯平台工厂模式

adb命令启动展讯工厂模式: adb shell am start com.sprd.engineermode/com.sprd.engineermode.EngineerModeActivity...

东街小霸王
18分钟前
0
0
mtu值怎样设置才网速最快

一、什么是 MTU 值 1 从字面上来说,MTU 是英文 Maximum Transmission Unit 的缩写,即最大传输单元,它的单位是字节。 在我们常用的以太网中,MTU 一般是 1500,而无线路由器默认一般是 14...

Clarence_D
36分钟前
1
0
McAfee阻止邮件发送功能

自己写的邮件发送功能,在本地机器上可以发送,但是放到服务器上面之后就不能发送了,捕获到的异常是“以一个访问权限不允许的方式做了一个访问套接字的尝试”,找了很久,终于发现是被McAfe...

壹峰
41分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部