短信盜刷和短信轟炸是項(xiàng)目開(kāi)發(fā)中必須要解決的問(wèn)題之一,它的優(yōu)先級(jí)不亞于 SQL 注入的問(wèn)題,同時(shí)它也是面試中比較常見(jiàn)的一個(gè)經(jīng)典面試題,今天我們就來(lái)看下,如何防止這個(gè)問(wèn)題。
短信盜刷和短信轟炸的概念如下:
短信盜刷和短信轟炸屬于一類問(wèn)題,可以一起解決。但這類問(wèn)題的解決,不能依靠某一種解決方案,而是多種解決方案共同作用,來(lái)預(yù)防此類問(wèn)題的發(fā)生。
這類問(wèn)題的綜合解決方案有以下幾個(gè):
具體實(shí)現(xiàn)如下。
圖形驗(yàn)證碼的執(zhí)行流程如下:
當(dāng)用戶點(diǎn)擊“發(fā)送短信驗(yàn)證碼”的時(shí)候,前端程序請(qǐng)求后端生成圖形驗(yàn)證碼,后端程序生成圖形驗(yàn)證碼的功能,可以借助 Hutool 框架來(lái)生成,它的核心實(shí)現(xiàn)代碼如下:
@RequestMapping("/getcaptcha")public AjaxResult getCaptcha(){ // 1.生成驗(yàn)證碼到本地 // 定義圖形驗(yàn)證碼的長(zhǎng)和寬 LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(128, 50); String uuid = UUID.randomUUID().toString().replace("-",""); // 圖形驗(yàn)證碼寫出,可以寫出到文件,也可以寫出到流 lineCaptcha.write(imagepath+uuid+".png"); // url 地址 String url = "/image/"+uuid+".png"; // 將驗(yàn)證碼存儲(chǔ)到 redis redisTemplate.opsForValue().set(uuid,lineCaptcha.getCode()); HashMap<String,String> result = new HashMap<>(); result.put("codeurl",url); result.put("codekey",uuid); return AjaxResult.succ(result);}
上述執(zhí)行代碼中有兩個(gè)關(guān)鍵操作:第一,生成圖形驗(yàn)證碼,并返回給前端程序;第二,將此圖形驗(yàn)證的標(biāo)識(shí)(ID)和正確的驗(yàn)證碼保存到 Redis,方便后續(xù)驗(yàn)證。
前端用戶拿到圖形驗(yàn)證碼之后,輸入圖形驗(yàn)證碼,請(qǐng)求后端程序驗(yàn)證,并發(fā)送短信驗(yàn)證碼。
后端程序拿到(圖形)驗(yàn)證碼之后,先驗(yàn)證(圖形)驗(yàn)證碼的正確性.如果正確,則發(fā)送短信驗(yàn)證碼,否則,將不執(zhí)行后續(xù)流程并返回執(zhí)行失敗給前端,核心實(shí)現(xiàn)代碼如下:
// redis 里面 key 對(duì)應(yīng)的真實(shí)的驗(yàn)證碼String redisCodeValue = (String) redisTemplate.opsForValue().get(user.getCodeKey());// 驗(yàn)證 redis 中的驗(yàn)證碼和用戶輸入的驗(yàn)證碼是否一致if (!StringUtils.hasLength(redisCodeValue) || !redisCodeValue.equals(user.getCheckCode())) { // 驗(yàn)證碼不正確 return AjaxResult.fail(-1, "驗(yàn)證碼錯(cuò)誤");}// 清除 redis 中的驗(yàn)證碼redisTemplate.opsForValue().set(userInfoVO.getCodeKey(), "");// 請(qǐng)求短信 API 發(fā)送短信業(yè)務(wù)......
IP 限制可以在網(wǎng)關(guān)層 Spring Cloud Gateway 中實(shí)現(xiàn),在 Gateway 中使用全局過(guò)濾器來(lái)完成 IP 限制,核心實(shí)現(xiàn)代碼如下:
@Componentpublic class IpFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 獲取請(qǐng)求 IP String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); Long count = redisTemplate.opsForValue().increment(ip, 1); // 累加值 if(count >= 20){ // 大于最大執(zhí)行次數(shù) redisTemplate.opsForValue().decrement(ip, 1); // 變回原來(lái)的值 // 終止執(zhí)行 response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED); return response.setComplete(); } redisTemplate.expire(ip, 1, TimeUnit.DAYS); // 設(shè)置過(guò)期時(shí)間 // 執(zhí)行成功,繼續(xù)執(zhí)行后續(xù)流程 return chain.filter(exchange); }}
其中,訪問(wèn)次數(shù)使用 Redis 來(lái)存儲(chǔ)。
IP 黑名單可以在網(wǎng)管層面通過(guò)代碼實(shí)現(xiàn),也可以通過(guò)短信提供商提供的 IP 黑名單來(lái)實(shí)現(xiàn)。
例如,阿里云短信提供的 IP 黑名單機(jī)制,如下圖所示:
通過(guò)以上設(shè)置之后,我們就可以將監(jiān)控中有問(wèn)題的 IP 設(shè)置為黑名單,此時(shí) IP 黑名單中的 IP 就不能調(diào)用短信的發(fā)送功能了。
PS:網(wǎng)關(guān)層面實(shí)現(xiàn) IP 黑名單,可以參考添加 IP 限制的代碼進(jìn)行改造。
驗(yàn)證碼的發(fā)送頻次,可以通過(guò)網(wǎng)關(guān)或短信提供商來(lái)解決。以阿里云短信為例,它可以針對(duì)每個(gè)手機(jī)號(hào)設(shè)置每分鐘、每小時(shí)、每天的短信最大發(fā)送數(shù),如下圖所示:
當(dāng)然,這個(gè)值也可以人為修改,但阿里云短信每天單個(gè)手機(jī)號(hào)最多支持發(fā)送 40 條短信。
短信提供商通常會(huì)提供防盜、防刷的機(jī)制。例如,阿里短信它可以設(shè)置短信發(fā)送總量閾值報(bào)警、套餐余量提醒、每日/每月發(fā)送短信數(shù)量限制等功能,如下圖所示:
本文鏈接:http://www.tebozhan.com/showinfo-26-74675-0.html面試官:如何防止短信盜刷和短信轟炸?
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: DartVM GC 深度剖析