1 小豆社保業(yè)務(wù)及需求
半夜短信費用完, 怎么知道是否有問題?
小豆社保:是一家一站式人力資源SAAS服務(wù)云智慧平臺,隸屬于北京新琪科技有限公司, 說簡單點就是解決工作變動無掛靠單位的人代繳社保的業(yè)務(wù)。
阿亮: 小豆社保CTO, 原安邦集團(tuán)系統(tǒng)架構(gòu)師 。
需求(半夜電話): 最近業(yè)務(wù)增長迅猛,我們公司預(yù)存的短信條數(shù)用完, 短信服務(wù)商半夜無法充值,怎么辦?
上次充值短信條數(shù)不少, 好像比計劃提早很多用完,是否有被盜刷的情況 ?
解決方案(回復(fù)): 下載短信防火墻,做對接,
- 可以確保短信驗證碼不被盜刷,
- 云控制臺可以實時展現(xiàn)發(fā)送短信的詳細(xì)數(shù)據(jù)
對接需要多久?產(chǎn)品經(jīng)理反對出現(xiàn)谷歌驗證碼及類似的東東
1 對接需要投入多少人日,現(xiàn)在業(yè)務(wù)多,技術(shù)資源緊缺,
2 我們產(chǎn)品正在推廣期,產(chǎn)品經(jīng)理強(qiáng)烈反對增加像 12306 那樣low 的驗證方式, 人家是市場壟斷地位,再多人吐槽也不改變, 我們不愿新來的客戶一看注冊流程太麻煩不再使用我們的產(chǎn)品,
如圖:是我們的登錄/注冊頁面,要求在頁面上不能增加任何用戶交互流程。
解決方案(回復(fù)):
1 一般熟悉的技術(shù),半個人日就可以解決。
2 企業(yè)短信防火墻在任何時候,都不會出現(xiàn)類似谷歌驗證碼,如12306 那樣的二次驗證,完全符合需求。
2 企業(yè)短信防火墻接口對接
2.0 企業(yè)短信網(wǎng)關(guān)接入
首先解決多通道接入,以免單獨單獨通道出現(xiàn)問題導(dǎo)致整個業(yè)務(wù)受影響,
小豆社保目前用的是億美軟通短信接口, 采用企業(yè)短信網(wǎng)關(guān)后, 自動可以分配到其他短信通道, 目前配置中增加了助通科技的短信通道, 看配置文件 :sms_config.json
按50%的量配置
{
"route": {
"ztinfo":"50",
"emay":"50"
},
"emay": {
"smsUrl": "http://www.btom.cn:8080",
"appId": "",
"secretKey": ""
},
"ztinfo": {
"smsUrl": "http://api.mix2.zthysms.com",
"username": "",
"password": "!"
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
發(fā)送短信接口 ,本次是調(diào)用客戶端接口,訪問服務(wù)的方式 (也可以本地調(diào)用)
public JSONObject sendMsg(String phone, String msg) {
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("phone", phone);
paramsMap.put("msg", msg);
logger.debug("msg=" + msg);
String jsonResp = HttpClient.execClient("fireWareUrl", "SendSmsServlet", paramsMap, 1000);
try {
JSONObject jsonRet = jsonResp != null ? JSONObject.parseObject(jsonResp) : null;
int ret = jsonRet != null ? jsonRet.getIntValue("ret") : -1;
if (ret != 0) {
logger.error("sendMsg() paramsMap=" + paramsMap + "|jsonResp=" + jsonResp);
} else {
String spCode = jsonRet != null ? jsonRet.getString("spCode") : null;
logger.info("sendMsg() spCode=" + spCode + "|phone=" + phone + "|msg=" + msg);
}
return jsonRet;
} catch (Exception e) {
logger.error("sendMsg() paramsMap=" + paramsMap + "|jsonResp=" + jsonResp);
return null;
}
}
public JSONObject sendTpMsg(String phone, String templateId, Map<String, String> templateMap) {
Map<String, Object> paramsMap = new HashMap<>();
String templateJson = templateMap != null ? JSONObject.toJSONString(templateMap) : null;
paramsMap.put("phone", phone);
paramsMap.put("templateId", templateId);
paramsMap.put("templateJson", templateJson);
String jsonResp = HttpClient.execClient("fireWareUrl", "SendSmsServlet", paramsMap, 1000);
try {
JSONObject jsonRet = (jsonResp != null) ? JSONObject.parseObject(jsonResp) : null;
int ret = jsonRet != null ? jsonRet.getIntValue("ret") : -1;
if (ret != 0) {
logger.error("sendTpMsg() ret=" + ret + " paramsMap=" + paramsMap + "|jsonResp=" + jsonResp);
} else {
String spCode = jsonRet != null ? jsonRet.getString("spCode") : null;
logger.info("sendTpMsg() spCode=" + spCode + "|phone=" + phone + "|templateId=" + templateId + "|templateJson=" + templateJson);
}
return jsonRet;
} catch (Exception e) {
logger.error("sendTpMsg() paramsMap=" + paramsMap + "|jsonResp=" + jsonResp);
return null;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
好,開始對接的三步
2.1 第 一步:獲取防火墻帳號密鑰
進(jìn)入 防火墻控制臺,在左側(cè)導(dǎo)航欄選擇【網(wǎng)站管理】,進(jìn)入網(wǎng)站管理頁面,單擊【發(fā)到郵箱】接收密鑰。
2.2 第二步:下載防火墻服務(wù)器
前往新昕科技官網(wǎng),在頂部導(dǎo)航欄選擇【解決方案】>【下載中心】,進(jìn)入下載中心頁面,找到短信防火墻服務(wù)器安裝包,點擊【下載鏈接】即可下載。
2.3 第三步:業(yè)務(wù)系統(tǒng)前后端接入
1) web 前端接入:
Java 在頁面合適的位置(標(biāo)簽內(nèi))加入以下代碼引入JS文件:
由于是Vue 前端結(jié)構(gòu), 需要增加 JS 引入的配置 main.js
Vue.component("remote-script", {
render: function(createElement) {
var self = this;
return createElement("script", {
attrs: {
type: "text/javascript",
src: this.src
},
on: {
load: function(event) {
self.$emit("load", event);
},
error: function(event) {
self.$emit("error", event);
},
readystatechange: function(event) {
if (this.readyState == "complete") {
self.$emit("load", event);
}
}
}
});
},
props: {
src: {
type: String,
required: true
}
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
編譯后的Vue前臺頁面
<html><head><meta charset=utf-8><meta name=baidu-site-verification content=L5waao0Tb7>
<meta name=viewport content="width=device-width,initial-scale=1,user-scalable=0,minimum-scale=1,maximum-scale=1,user-scalable=no">
<title>小豆企服</title><meta name=keywords content=小豆企服,小豆社保,代繳社保,社保補(bǔ)繳,公積金政策咨詢,稅務(wù)優(yōu)化,企業(yè)薪酬服務(wù),企業(yè)社保代理,個人社保>
<meta name=description content=小豆企服致力于為全國企業(yè)提供一站式互聯(lián)網(wǎng)+薪酬服務(wù),包括全國企業(yè)社保代理、薪酬稅務(wù)優(yōu)化、個人社保代繳補(bǔ)繳、企業(yè)薪酬服務(wù)、社保掛靠等,為企業(yè)和個人提供便捷的社會保障服務(wù)。>
<script type=application/ld+json>{
"@context": "https://ziyuan.baidu.com/contexts/cambrian.jsonld",
"@id": "http://m.xiaodoushebao.com",
"appid": "1616534637710048",
"title": "小豆社保",
"images": ["http://m.xiaodoushebao.com/pic2.png",
"http://m.xiaodoushebao.com/pic3.png"
],
"pubDate": "2018-12-11T18:30:01"
}</script>
<link href=/static/css/app.02362ec5360e850f7e7a305657c73504.css rel=stylesheet></head>
<body><div id=app-box></div>
<script src=https://api.xiaodoushebao.com/NxtJsServlet></script>
<script type=text/javascript src=/static/js/vendor.412e5601a76d0bfa4f60.js></script>
<script type=text/javascript src=/static/js/app.6bb9c7188bfad4414c77.js></script>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
2) 后端接入:
Java
修改配置(和業(yè)務(wù)系統(tǒng)同系統(tǒng)不需要修改):
newxtc.ini (存放位置:"/WEB-INF/classes/newxtc.ini")
修改參數(shù)(fireWareUrl)--> fireWareUrl=http://localhost:7502
短信下發(fā)
public RetMsg smsSend(HttpServletRequest request, HttpServletResponse response, String clientMobile) {
RetMsg retMsg = new RetMsg(-1, "系統(tǒng)異常");
FwClient fwClient = new FwClientImpl();
try {
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 {
if(smsRetMsg != null && smsRetMsg.getRet() == 0) {
fwClient.execSucc(paramMap);
logger.debug("send succ");
retMsg.setRet(0);
retMsg.setMsg("發(fā)送驗證碼成功");
}
else {
SmsVerifyCache.getInstance().remove(clientMobile);
fwClient.execFail(paramMap);
retMsg.setRet(-1);
retMsg.setMsg("發(fā)送驗證碼失敗");
}
}
}
catch(Exception e) {
for(StackTraceElement elment: e.getStackTrace()) {
logger.error(elment.toString());
}
}
return retMsg;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
短信驗證
public RetMsg smsVerify(HttpServletRequest request, HttpServletResponse response, String clientMobile, String smsVerifyCode) {
FwClient fwClient = new FwClientImpl();
RetMsg retMsg = new RetMsg(-1, "系統(tǒng)異常");
if(smsVerifyCode == null || smsVerifyCode.isEmpty()) {
retMsg.setRet(1);
retMsg.setMsg("輸入驗證碼為空");
}
else {
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("請求過于頻繁");
}
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) {
fwClient.execSucc(paramMap);
}
else {
fwClient.execFail(paramMap);
}
}
return retMsg;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
3 對接完成后的界面有啥秘密?
看起來和原來一樣, 但抓一下報文,發(fā)現(xiàn)不一樣的地方:
3.1 頁面多了一行代碼 , 引入設(shè)備指紋
便于定位設(shè)備,甚至可以反向抓出IP 等信息,信息越多,這就有可能追溯到攻擊者哦。
<script src='https://api.xiaodoushebao.com/NxtJsServlet'></script>
3.2 報文增加了加密及混淆表單名稱
抓取的報文,熟悉加解密算法的高手一看就明白,
- 手機(jī)號做加密了
- 表單名稱做了混淆
熟悉表單的工程師肯定知道報文加密后很難搞的, 不如用爬蟲工具,
但爬蟲工具有反爬措施,一般人也搞不定,即使搞定了,還有下一個坑等著呢
一般爬蟲模擬攻擊, 防火墻識別后直接攔截。
4 豐富可視化實時風(fēng)險大盤,
小豆社保提的疑問(需求): 上次充值短信條數(shù)不少, 好像比計劃提早很多用完,是否有被盜刷的情況 ?
回復(fù)(解決方案): 通過數(shù)據(jù),是否有被盜刷的情況一清二楚。
防御攔截數(shù)據(jù)盡收眼底,實時查看當(dāng)日數(shù)據(jù)詳情與近期風(fēng)險趨勢。
通過風(fēng)控數(shù)據(jù)看板,可查看1-30天的驗證情況、風(fēng)控攔截情況以及驗證事件觸發(fā)的AI模型情況。
進(jìn)入防火墻控制臺,在左側(cè)導(dǎo)航欄選擇【風(fēng)險大盤】,進(jìn)入風(fēng)險大盤頁面。