短信接口防刷防轰炸解决方案Java接入教程- 企业短信防火墙+ 【中昱维信】短信验证码_中昱维信模版配置-程序员宅基地

技术标签: 产品安全  java  web  短信安全  短信防轰炸  

一、企业短信防火墙的实现

1.1 简介

新昕科技在交易反欺诈核心上, 通过AI快速学习机制,结合国际领先的设备指纹技术,首次推出无需图形验证码机制的企业短信防火墙,三步完成下载对接。
在这里插入图片描述

1.2 第一步:获取防火墙帐号密钥

进入 防火墙控制台,在左侧导航栏选择【网站管理】,进入网站管理页面,单击【发到邮箱】接收密钥。
在这里插入图片描述

1.3 第二步:下载防火墙服务器

前往新昕科技官网,在顶部导航栏选择【解决方案】>【下载中心】,进入下载中心页面,找到短信防火墙服务器安装包,点击【下载链接】即可下载。

1.4 第三步:业务系统前后端接入

web 前端接入:
前端接入:
Web前端接入文档
Java 在页面合适的位置(标签内)加入以下代码引入JS文件:

<script type="text/javascript" src="/NxtJsServlet"></script>

PHP 在页面合适的位置(标签内)加入以下代码引入JS文件:

<script id="finger" type="text/javascript" src="/nxt_inc/nxt_front.php"></script>

后端接入:
Java
修改配置(和业务系统同系统不需要修改):
newxtc.ini (存放位置:"/WEB-INF/classes/newxtc.ini")
修改参数(fireWareUrl)–> fireWareUrl=http://localhost:7502
短信下发

public RetMsg smsSend(HttpServletRequest request, HttpServletResponse response, String clientMobile) {
    
    RetMsg retMsg = new RetMsg(-1, "系统异常");
    FwClient fwClient = new FwClientImpl();
    try {
    
        // 1 调用【短信防火墙】短信发送请求
        HashMap < String, Object > paramMap = fwClient.getSendReq(request, clientMobile);
        String jsonReq = fwClient.execReq(paramMap);
        String smsSendRet = fwClient.getRetVaule(jsonReq, "riskResult");
        if("REJECT".equals(smsSendRet)) {
    
            retMsg.setRet(3);
            retMsg.setMsg("请求过于频繁");
        }
        else {
    
            // 业务 TODO
            // 业务调用短信接口 TODO
            // 调用短信接口 结束
            if(smsRetMsg != null && smsRetMsg.getRet() == 0) {
    
                // 2 调用【短信防火墙】成功结果
                fwClient.execSucc(paramMap);
                logger.debug("send succ");
                retMsg.setRet(0);
                retMsg.setMsg("发送验证码成功");
            }
            else {
    
                // 2 调用【短信防火墙】失败结果
                SmsVerifyCache.getInstance().remove(clientMobile);
                fwClient.execFail(paramMap);
                retMsg.setRet(-1);
                retMsg.setMsg("发送验证码失败");
            }
        }
    }
    catch(Exception e) {
    
        for(StackTraceElement elment: e.getStackTrace()) {
    
            logger.error(elment.toString());
        }
    }
    return retMsg;
}

短信验证

public RetMsg smsVerify(HttpServletRequest request, HttpServletResponse response, String clientMobile, String smsVerifyCode) {
    
    FwClient fwClient = new FwClientImpl();
    RetMsg retMsg = new RetMsg(-1, "系统异常");
    if(smsVerifyCode == null || smsVerifyCode.isEmpty()) {
    
        retMsg.setRet(1);
        retMsg.setMsg("输入验证码为空");
    }
    else {
    
        // 1 调用【短信防火墙】验证请求
        HashMap < String, Object > paramMap = fwClient.getVerifyReq(request, clientMobile); // 请求防火墙
        String jsonReq = fwClient.execReq(paramMap);
        // 报文处理
        String smsSendRet = fwClient.getRetVaule(jsonReq, "riskResult");
        if("REJECT".equals(smsSendRet)) {
    
            retMsg.setRet(3);
            retMsg.setMsg("请求过于频繁");
        }
        // 业务 TODO
        if(cacheSmsVerify != null && cacheSmsVerify.getVerifyCode() != null && !cacheSmsVerify.getVerifyCode().isEmpty()) {
    
            if(cacheSmsVerify.getVerifyCode().equals(smsVerifyCode)) {
    
                retMsg.setRet(0);
                retMsg.setMsg("验证成功");
            }
            else {
    
                retMsg.setRet(1);
                retMsg.setMsg("验证码错误");
            }
        }
        else {
    
            retMsg.setRet(-9);
            retMsg.setMsg("验证码超时");
        }
        if(retMsg.getRet() == 0) {
    
            // 2 调用【短信防火墙】成功结果
            fwClient.execSucc(paramMap);
        }
        else {
    
            // 2 调用【短信防火墙】失败结果
            fwClient.execFail(paramMap);
        }
    }
    return retMsg;
}

1.5丰富可视化实时风险大盘,

防御拦截数据尽收眼底,实时查看当日数据详情与近期风险趋势。
通过风控数据看板,可查看1-30天的验证情况、风控拦截情况以及验证事件触发的AI模型情况。
进入防火墙控制台,在左侧导航栏选择【风险大盘】,进入风险大盘页面。
在这里插入图片描述

二、短信验证码的实现

2.1 简介

企业防火墙只能防止机器人脚本恶意攻击网站或App,如何识别到是本人操作的,还需要结合短信验证码进一步进行身份识别。本文以注册为例,在SpringMVC+Spring+Mybatis框架的基础上完成该短信验证码功能。

发送短信验证码的原理是:随机生成一个4-6位数字,将该4-6位数字保存到session当中,客户端通过sessionid判断对应的session,用户输入的验证码再与session记录的验证码进行比较。

一般的第三方短信平台都会有他们自己的短信接口,只要读懂他们的接口稍作稍作改变就能满足自己的需求。

首先将短信平台接口代码列出:这里需要依赖的三个通用jar包 commons-logging-1.1.1.jar,commons-httpclient-3.1.jar,commons-codec-1.4.jar。

2.2 短信服务商接入

开发短信验证码功能通常是采用第三方短信服务商的服务,作为短信下发渠道,以这个网站短信验证码为例:上海中昱文化传播有限公司【简称中昱维信】成立于2010年,是一家从事增值电信业务和软件开发服务的科技企业。获取试用验证码条数和验证码接口文档,进行接口对接前需首先进行准备工作:

短信签名报备

短信验证码需预先设置短信签名,签名会经过平台审核,审核通过后才可作为接口参数使用。
在这里插入图片描述
短信验证码模板报备

短信验证码需预先设置短信模板,签名会经过平台审核,审核通过后才可作为接口参数使用。

获取appId和appKey

为保障接口安全,短信验证码接口,使用多重加密的appId和appKey进行身份鉴权和校验,这两个字段作为验证码接口必填项,建议预先获取到,获取appKey时需要对注册人进行身份校验。

至此,短信服务商验证码接口已经准备完毕,接下来可以进行业务场景,进行短信验证码服务的开发,下面展示通用的短信验证码接入流程。
2.3 短信验证码代码实现

短信验证码前端较为简单,主要就是发送验证码和校验验证码两个ajax请求,结合上面的滑动验证可实现双重验证。前端页面结构如下:

   <html>
    <head>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0">
        <!-- 国内使用 -->
        <link rel="stylesheet" href="https://cdn.staticfile.org/amazeui/2.7.2/css/amazeui.min.css">
        <script type="text/javascript" charset="utf-8" src="https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js"></script>
    </head>
    <body>
     
    <div class="am-form">
        <div class="am-form-group">
            <label for="tel">请输入手机号</label>
            <input type="text" class="" id="tel" placeholder="请输入手机号">
        </div>
     
        <div id="__nc" style="height: 70px">
            <div id="nc"></div>
        </div>
     
        <div class="am-form-group">
            <label for="code">请输入验证码</label>
            <input id="code" type="text" placeholder="请输入验证码">
        </div>
     
        <button type="button" class="am-btn am-btn-primary">提交</button>
    </div>
     
    <script>
        var nc_token = ["CF_APP_1", (new Date()).getTime(), Math.random()].join(':');
        var nc=NoCaptcha.init({
     
            renderTo: '#nc',
            appkey: 'CF_APP_1',
            scene: 'register',
            token: nc_token,
            trans: {
     "key1": "code200"},
            elementID: ["usernameID"],
            is_Opt: 0,
            language: "cn",
            timeout: 10000,
            retryTimes: 5,
            errorTimes: 5,
            inline:false,
            apimap: {
     
    // 'analyze': '//a.com/nocaptcha/analyze.jsonp',
    // 'uab_Url': '//aeu.alicdn.com/js/uac/909.js',
            },
            bannerHidden:false,
            initHidden:false,
            callback: function (data) {
     
                window.console && console.log(nc_token)
                window.console && console.log(data.csessionid)
                window.console && console.log(data.sig);
                var tel = $('#tel').val();
                $.ajax({
     
                    url: "sendCode",
                    type: "post",
                    data: {
     
                        tel:tel
                    },
                    dataType: "json",
                    success: function (result) {
     
                        if (result.code == 0) {
     
                            alert("验证码已发送!", "green")
                        } else {
     
                            alert("发送失败,请稍后再试!");
                            nc.reset()
                        }
                    },
                    error: function () {
     
                        alert("系统繁忙,请稍后再试!", "red")
                    }
                })
            },
            error: function (s) {
     
            }
        });
        NoCaptcha.setEnabled(true);
        nc.reset();//请务必确保这里调用一次reset()方法
     
        NoCaptcha.upLang('cn', {
     
            'LOADING':"加载中...",//加载
            'SLIDER_LABEL': "请向右滑动验证",//等待滑动
            'CHECK_Y':"验证通过",//通过
            'ERROR_TITLE':"非常抱歉,这出错了...",//拦截
            'CHECK_N':"验证未通过", //准备唤醒二次验证
            'OVERLAY_INFORM':"经检测你当前操作环境存在风险,请输入验证码",//二次验证
            'TIPS_TITLE':"验证码错误,请重新输入"//验证码输错时的提示
        });
    </script>
    </body>
    </html>

后端代码主要职责是两方面:1)接收生成验证码请求,生成验证码存入session中;2)接收校验验证码的请求,将存入session的验证码去除,与前端输入的验证码进行比对,比对一致则通过并进行视图转发,比对不一致则告知前端错误原因。主要实现代码如下:

    HttpSession session = req.getSession();
    // 验证码有效时间
    session.setMaxInactiveInterval(600);
    try {
    
        Integer num = RandNumber.getNum();
        //  发送验证码通道
        Sendsms.Send(num, phone);
        session.setAttribute(phone, num);
        return R.ok();
    } catch (Exception e) {
    
        e.printStackTrace();
        logger.error(e.getMessage());
        return R.error("fasle");
    }

    import java.io.Exception;
     
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.HttpException;
    import org.apache.commons.httpclient.NameValuePair;
    import org.apache.commons.httpclient.methods.PostMethod;
     
    public class Sendsms {
    
     
      private static String Url = "https://vip.veesing.com/smsApi/verifyCode";
     
      // 发送短信验证码
      public static void Send(Integer num, String mobile) {
    
        try {
    
        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(Url);
        client.getParams().setContentCharset("UTF-8");
        method.setRequestHeader("ContentType", "application/x-www-form-urlencoded;charset=UTF-8");
        NameValuePair[] data = {
     
            new NameValuePair("appId", "*********"),
            new NameValuePair("appKey", "**********"), 
            new NameValuePair("templateId", "*******"), 
            new NameValuePair("mobile", "*******"),
            new NameValuePair("variables", "*******") 
            };
        method.setRequestBody(data);
        client.executeMethod(method);
        String submitResult = method.getResponseBodyAsString();
        System.out.println(submitResult);
        } catch (Exception e) {
    
          e.printStackTrace();
        }
      }
     
    }

    HttpSession session = req.getSession();
    String yzm = String.valueOf(session.getAttribute(username));
    logger.info(yzm);
    if (yzm == null) {
    
        return R.error("验证码错误");
    }
    if (yzm != null && !verifycode.equals(yzm)) {
    
        return R.error("验证码错误");
    }

以上就是Java实现企业短信防火墙与短信验证码的全部实现,基于此案例,可实现安全性高、用户体验好的登录注册+企业短信防火墙+短信验证码功能。

原地址:短信接口被恶意调用?【新昕科技】企业短信防火墙+【中昱维信】短信验证码【Java应用实例】

如有问题可在留言区展开讨论哦,欢迎转发,如有改动请站内信通知本文作者,谢谢!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46641057/article/details/113520673

智能推荐

Logstash:运用 jdbc_streaming 来丰富我们的数据_logstash jdbc_streaming-程序员宅基地

文章浏览阅读2.8k次,点赞4次,收藏7次。在IoT物联网时代,我们经常会遇到从传感器采集数据的情况。这些传感器,可以上传物联网数据,比如温度,湿度。通常这些传感器带有自己的ID,但是它并不具有像地理位置等这样的信息。当物联网数据传到我们的数据平台时,我们希望对采集上来的数据进行数据的丰富,比如我们对物联网的数据加上它所在的位置等信息,这将对我们的数据分析非常有用。这些需要丰富的数据通常会存放于一个关系数据库的表格中,比如MySQL的数据库..._logstash jdbc_streaming

工业数据分析技术与实战之入门——昆仑数据田春华培训听课记录_工业数据分析 实战培训-程序员宅基地

文章浏览阅读512次。田老师发音不标准啊,好多词听好几遍,再关联上下文,连猜带蒙的才勉强能明白,不过有的也不一定对。记录以反复学习。视频链接:https://appgzdr0r6c3350.h5.xiaoeknow.com/v1/course/column/p_5e90181d2f5c2_Ut1xWLXN?type=3&share_user_id=u_5e91169429c27_G0xxVfLReS&share_type=2&scene=%E5%88%86%E4%BA%AB&access_en_工业数据分析 实战培训

Cesium聚簇实现-kdbush原理-程序员宅基地

文章浏览阅读2.9k次,点赞4次,收藏16次。Cesium聚簇实现-kdbush源码剖析文章目录问题说明KDbush库的分块重排序算法说明KDbush库的查找范围点算法说明矩形框范围查找圆形范围查找  上一篇文章通过调试发现Cesium实现点聚簇过程中一个bug,从中猜测其实现聚簇核心代码在kdbush类中,本文展开kdbush类查看它是如何实现点聚簇效果的。问题说明  假设二维平面中有10个点,分别为ABCDEFGHIJ,如下图所示..._kdbush

linux 内核模块,Linux内核模块(一)-程序员宅基地

文章浏览阅读147次。Linux的模块化配置:将公版部分(常用的)编译到内核中,个性化部分(不常用的/驱动程序)独立出来编译成模块在用户空间中进行加载所需的模块到内核中[root@rhel6~]#ls/lib/modules/$(uname-r)/kernelarchcryptodriversfskernellibmmnetsoundarch..._config_vfat_fs

大数相减 计算n个a相减_输入两个整数a(大于等于1且小于等于9)和n(大于等于1且小于等于80),编程求得并输出-程序员宅基地

文章浏览阅读8.5k次,点赞3次,收藏37次。输入两个整数a(大于等于1且小于等于9)和n(大于等于1且小于等于80),编程求得并输出下面等式的值:例如:若输入的a为5,n为6,则要计算下面公式的值:【输入形式】从标准输入读入整数a和n,两者之间以一个空格分隔。【输出形式】在标准输出上输出公式的计算结果。【样例1输入】5 6【样例1输出】493830【样例1说明】输入的a为5,n为6,按照上述公式计..._输入两个整数a(大于等于1且小于等于9)和n(大于等于1且小于等于80),编程求得并输出

UTexture2D 转为png_uasset转png-程序员宅基地

文章浏览阅读2.1k次。bool UCamerTexture::ExprotUTexture2D(UTexture2D* Img,FString fileDestination){ TextureCompressionSettings OldCompressionSettings = Img->CompressionSettings; //TextureMipGenSettings OldMipGenSet..._uasset转png

随便推点

python高阶知识之——字典/集合推导式_字典推导式 key自增怎么写-程序员宅基地

文章浏览阅读205次。什么是推导式:推导式是用来快速的生成数据1、推导式类型2、字典推导式推导式结合条件语句语法:dict = { key:value for i in xxx if 条件}推导式结合三元运算符语法:dict = { key:value if 条件 else key2:value2 for i in xxx}3、字典推导式原则4、注意事项5、集合推导式......_字典推导式 key自增怎么写

C语言经典编程之字符串_char ch : input-程序员宅基地

文章浏览阅读1.5k次,点赞6次,收藏18次。C语言经典编程之字符串:按特定顺序输出压缩,IP地址判断是否合法,字符串压缩、解压、排序,查找相同的字串,单词升序排列,统计单词个数,Objective-C和C++命名之争,字符串删除、插入、替换、抽取、交换、拼接、分割,统计字母在字符串中出现的次数等。_char ch : input

EXCEL高级技巧_在exce设置t形-程序员宅基地

文章浏览阅读917次。也许你已经在Excel中完成过上百张财务报表,也许你已利用Excel函数实现过上千次的复杂运算,也许你认为Excel也不过如此,甚至了无新意。但我们平日里无数次重复的得心应手的使用方法只不过是Excel全部技巧的百分之一。本专题从Excel中的一些鲜为人知的技巧入手,领略一下关于Excel的别样风情。 一、让不同类型数据用不同颜色显示   在工资表中,如果想让大于等于2000元_在exce设置t形

java解析xml文件_java 解析 xml 版本2.0-程序员宅基地

文章浏览阅读1.4w次,点赞7次,收藏33次。java解析xml常用的2种方法第一种 dom解析第二种 dom4j解析<?xml version="1.0" encoding="UTF-8"?><books> <book id="001"> <id>9</id> <title>Harry Potter</title> <author>J K. Rowling</author> </bo_java 解析 xml 版本2.0

c语言判断结构体一项是否为空,golang结构体怎么判断是否为空-程序员宅基地

文章浏览阅读2.1k次。golang结构体怎么判断是否为空golang结构体怎么判断为空?就是判断是否已经初始化,方法如下:可以使用if objectA== (structname{}){ // your code },进行判断。示例代码如下:package mainimport ("fmt""reflect")type A struct{name stringage int}func (a A) IsEmpty() b..._判断结构体是否为空

Oracle 10.2.0.4 升级到 10.2.0.5-程序员宅基地

文章浏览阅读457次。发票开发测试库升级升级前准备,此次升级只是很对测试环境数据库升级,所以没有事先一个月来获取系统,数据库的统计信息,机器性能比对为了加快升级只是清理了以下信息01.截断SYS.AUD$基表:SQL>TRUNCATE TABLE SYS.AUD$;02.清理DBA回收站:SQL>purge DBA_RECYCLEBIN;1.升级开始,升级前首先断开测试环境的中间件..._oracle10.2.0.4 升级到10.2.0.5