1. 程式人生 > >下發短信功能的實現,卡洛思接口的使用,

下發短信功能的實現,卡洛思接口的使用,

eip quest image urn ava http equals index 信息

因為公司的業務需要調用短信下發第三方接口,實現短信下發功能的開發。

這裏選取的第三方接口是卡洛思接口,短信接口有很多,不同的接口實現的方式有一天區別。

卡洛思接口,直接調用一下它封裝好的方法就可以實現了,因此這部分其實不太需要花精力去關註。

項目的部分,因為考慮到需要防止惡意用戶故意去網站下發短信,所以需要做一些安全的防護,

所以這部分內容重點還是放在了關於短信模板中一個短連接的生成,以及安全防護的設計上了。

關於卡洛思平臺的接口文檔,跟它封裝好的案例代碼,可以到下面這個網站去取

http://118.31.17.45:8899/Index.aspx

需要註冊的信息,就需要用戶自己去註冊一個賬號了,到時候代碼開發會用到的。

基本的短信下發調用代碼如下

    public static String url1 = "http://118.31.17.45:8899/sms.aspx";  //請求接口,
    public static String userss = "2341";            //企業ID固定的
    public static String account = "你的個人賬戶";  //平臺賬戶
    public static String password = "你的個人密碼";      //平臺密碼

   然後配置完了以後,
   String msg = SmsClientSend.sendSms(url1, userss, account,
                password, phone, content);
    直接調用下發短信的接口就可以了,其中phone是要發送過去的手機號碼,
    content是短信模板,其中模板需要公司的簽名為前綴,比如
   【XX公司標誌】尊敬的客戶,你好!

其中,由於短信模板裏面帶有一個短連接,為了防止短信字數多長,需要對原始的鏈接進行重新跳轉的處理,

因此將原始的長鏈接轉換為短連接發送,這裏短連接一般是固定的位數的,根據一定的算法進行重整生成。

這裏使用了一個微博的短連接生成接口,

http://api.weibo.com/2/short_url/shorten.json?source=2849184197&url_long=【你的請求域名】?parameter=value

只要在短連接第三方生成接口裏面加上你原本鏈接的請求域名,以及你要傳遞的參數就可以生成新的短連接了。

我在開發的時候,對於短連接的返回的內容

技術分享圖片

需要提取的短連接部分是 url_short部分,不過因為返回的格式一開始是有問題的,不是標準的json格式,

所以,需要對返回的數據進行一定的切割提取。

下面是切割提取短連接的代碼片段

/**
     * 生成短連接
     * @param user 附帶userid參數,你可以根據需要附帶你想要傳遞的參數
     * @return
     */
    public String cutLink(User user){
        JSONObject jsonobj  = null;
        SmsController link = new SmsController();
        String url = "http://api.weibo.com/2/short_url/shorten.json?source=2849184197&" +
                "url_long=【替換為你的域名】?userId="+user.getUserid();
        try {
            String jsonString = link.sendGet(url);  //這裏請求回接口的返回數據
            System.out.println("****"+jsonString+"****");
            jsonobj = JSONObject.parseObject(jsonString);
            String r  = jsonobj.getString("urls");    //獲取返回的數據裏的urls部分,
            System.out.println(r);
            r=r.replace("[", "");
            r=r.replace("]", "");  //去掉最外層的[]括號,獲取json的標準格式 
            jsonobj =JSONObject.parseObject(r);
            System.out.println(jsonobj.getString("url_short"));   //最後才獲取url_short短鏈接
        } catch (Exception e) {
            System.out.printf(e.toString());
        }
        return jsonobj.getString("url_short");
    }

處理完基本的短信部分,接下來講一些一開始的短信安全防範思路,也是一開始的思路,比較簡單的一種處理方式

就是對客戶提交的手機號的同時,可以獲取客戶的cookie,ip,手機號信息,

為了方式客戶多次提交,以及防止不良用戶的故意多次刷短信,

需要對每次的次數進行限制,這裏的限制可以根據每個人的需要去設計。

比如說對對方的IP在某個時間段內限制訪問30次,同時該手機最多不能超過5次訪問。

這個感覺也是要根據實際的業務需求去進行更改的。

限制次數代碼

        //根據接收的request獲取ip
        ServletRequestAttributes attr=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request =attr.getRequest();

        String ip = getIpAddr(request);

        //IpTime 保存了每一個Ip的訪問次數,訪問時間
        Iptime iptime = iptimeService.getIpTimes(ip); 
        
       //開始判斷用戶的訪問次數,這一部分就是數據庫業務邏輯了
       if(iptime == null){
            Iptime tempiptime = new Iptime();
            tempiptime.setIptime(1);
            tempiptime.setIp(ip);
            tempiptime.setDeadtime(addDateMinut(1));
            if(user!=null)
                tempiptime.setUserid(user.getUserid());
            int insertflag = iptimeService.insert(tempiptime);
            if(insertflag>0){
                System.out.println("第一次訪問,新建iptime成功");
            }
        }
        if(iptime!=null){
            if(iptime.getIptime()>30){
                String deadline = iptime.getDeadtime(); //獲取限制30次時間以內的截止時間
                java.text.SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
                Date date = formatter.parse(deadline);
                Date now = new Date();
                if(now.getTime() < date.getTime()) {  //1個小時以內超過30次
                    System.out.println("11");
                    map.put("status", "0");
                    map.put("message", "ip次數訪問超過30次了!");
                    Phonedate phonedate = new Phonedate();
                    phonedate.setPhone(phone);
                    phonedate.setRecordtime(new Date());
                    int flag = phonedateService.insertPhonedate(phonedate);
                    if (flag > 0) {
                        System.out.println("保存好不符合的手機號了");
                    }
                    user.setAddtime(new java.sql.Date(new Date().getTime()));
                    userService.updateUser(user);
                    return callback + "(" + gson.toJson(map) + ")";
                }else{
                    iptime.setIptime(1);
                    iptime.setDeadtime(addDateMinut(1));
                    int insertflag = iptimeService.updateIptime(iptime);

                    if(insertflag>0){
                        System.out.println("時間超過了1小時了,次數變成1,時間從此刻開始計算");
                    }
                }
            }else{
                //沒有保存超過30次的,
                System.out.println("12");
                iptime.setIptime(iptime.getIptime()+1);
                int updateflag =iptimeService.updateIptime(iptime);
                if(updateflag>0){
                    System.out.println("更新成功了!");
                }
                String deadline = iptime.getDeadtime(); //獲取限制30次時間以內的截止時間
                java.text.SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
                Date date = formatter.parse(deadline);
                Date now = new Date();
                if(now.getTime() > date.getTime()){
                    iptime.setIptime(1);
                    iptime.setDeadtime(addDateMinut(1));
                    int insertflag = iptimeService.updateIptime(iptime);
                    if(insertflag>0){
                        System.out.println("ip訪問次數因為時間過了,次數變成1,重新開始計算,並且時間此刻開始計算");
                    }
                }
            }
        }
        Phonetime phonetime = phonetimeService.getPhoneTimes(phone);
        if(phonetime==null){
            Phonetime tempPhonetime = new Phonetime();
            tempPhonetime.setPhone(phone);
            tempPhonetime.setPhonetime(1);
            if(user!=null)
                tempPhonetime.setUserid(user.getUserid());
            int phoneFlag = phonetimeService.insert(tempPhonetime);  //這時候插入,需要手機號有對應的用戶才可以
            if(phoneFlag >0) {
                System.out.println("新建phoneFlag成功了");
            }
        }
        System.out.println("2");
        if(phonetime!=null){
            if(phonetime.getPhonetime()>=5){
                System.out.println("21");
                map.put("status","0");
                map.put("message","手機號次數訪問超過5次了!");
                Phonedate phonedate = new Phonedate();
                phonedate.setPhone(phone);
                phonedate.setRecordtime(new Date());
                int flag = phonedateService.insertPhonedate(phonedate);
                if(flag>0){
                    System.out.println("保存好不符合的手機號了");
                }
                user.setAddtime(new java.sql.Date(new Date().getTime()));
                userService.updateUser(user);
                return callback+"("+gson.toJson(map)+")";
            }else{
                System.out.println("22");
                //沒有超過5次的,
                phonetime.setPhonetime(phonetime.getPhonetime()+1);
                int phonetimeflag = phonetimeService.updatePhonetime(phonetime);
                if(phonetimeflag>0){
                    System.out.println("更新成功了!");
                }
            }
        }

        
    //獲取當前X小時候後的時間,String格式
     public static String addDateMinut(int hour){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        if (date == null)
            return "";
        System.out.println("front:" + format.format(date)); //顯示輸入的日期
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, hour);// 24小時制
        date = cal.getTime();
        System.out.println("after:" + format.format(date));  //顯示更新後的日期
        cal = null;
        return format.format(date);

    }

        /**
     * 獲取客戶端IP
     * @param request
     * @return
     */
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");

        System.out.println("x-forwarded-for ip: " + ip);
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理後會有多個ip值,第一個ip才是真實ip
            if( ip.indexOf(",")!=-1 ){
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            System.out.println("Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            System.out.println("WL-Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            System.out.println("HTTP_CLIENT_IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            System.out.println("X-Real-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            System.out.println("getRemoteAddr ip: " + ip);
        }
        System.out.println("獲取客戶端ip: " + ip);
        return ip;
    }

對於短信的下發此時的保護,還可以有多種方式,比如下發短信的時候,輸入圖形驗證碼,控制用戶的下發時間,可以減少訪問次數,

或者說當達到一定的次數,直接限制不能下發短信,

或許還可以有很多的方式,對於真正的安全防範,這種小兒科的措施肯定是不起作用的,也就是防範某些小白的操作罷了

或許你也有更多的方案呢。

下發短信功能的實現,卡洛思接口的使用,