前言:
現(xiàn)在基本上各種手機(jī)APP注冊(cè)都會(huì)用到手機(jī)驗(yàn)證碼,包括一些PC端網(wǎng)站也會(huì)使用手機(jī)號(hào)作為唯一標(biāo)識(shí)驗(yàn)證!
恰巧,小明的老板,讓其開(kāi)發(fā)一個(gè)用戶注冊(cè)的功能,并且強(qiáng)制用戶注冊(cè)綁定手機(jī),美其名曰為了提升安全性,呵呵噠,就是為了多擼一點(diǎn)用戶信息。
案例
一般來(lái)說(shuō),發(fā)送手機(jī)驗(yàn)證碼不能過(guò)于頻繁,前端發(fā)送按鈕點(diǎn)擊后一般會(huì)有一個(gè)60秒倒計(jì)時(shí)的功能。也就是說(shuō),如果用戶點(diǎn)擊發(fā)送一直沒(méi)有收到驗(yàn)證碼,只能60秒之后才可以進(jìn)行重發(fā)。
那么問(wèn)題來(lái)了,如果用戶繞過(guò)前端,直接向后臺(tái)API發(fā)送短信請(qǐng)求,然后寫個(gè)無(wú)限循環(huán)腳本,相信不久你的短信賬戶就會(huì)發(fā)來(lái)預(yù)警提示短信(一般來(lái)說(shuō)大的短信商都有預(yù)警設(shè)置功能)。
其實(shí)很簡(jiǎn)單,你只需要F12,查看發(fā)送請(qǐng)求就可以查找出后臺(tái)請(qǐng)求地址,然后你可以在控制臺(tái)輸入相關(guān)JS代碼,執(zhí)行個(gè)十萬(wàn)遍,是不是很爽?
這里以七牛云為測(cè)試案例,打開(kāi)注冊(cè)頁(yè)面,F(xiàn)12進(jìn)入調(diào)試模式,輸入手機(jī)號(hào),手動(dòng)點(diǎn)擊發(fā)送,獲取其短信發(fā)送后臺(tái)請(qǐng)求地址。下面是七牛云的一個(gè)短信發(fā)送請(qǐng)求,擼主測(cè)試了一下,顯然沒(méi)有達(dá)到擼主的預(yù)期,畢竟是大廠,防御措施還是做的很牛逼的。
以下是JS腳本,復(fù)制粘貼到控制臺(tái)回車就可以執(zhí)行:
var data = {"operation":1,"is_voice":false,"mobile_number":"17762018888","captcha_type":2};for (var i = 0; i < 10; i++) { $.ajax({ type: 'POST', contentType: 'application/json;charset=UTF-8', data:JSON.stringify(data), url: 'https://portal.qiniu.com/api/gaea/verification/sms/send', success: function(data) { console.log(data) } });}
控制臺(tái)返回以下信息,前三次請(qǐng)求成功,后面的就出現(xiàn)了驗(yàn)證碼校驗(yàn)并進(jìn)行了限流操作。
{"code":200,"message":""}{"code":200,"message":""}{"code":200,"message":""}{"code": 7209,"message":"captcha required"}{"code": 7209,"message":"captcha required"}{"code": 429,"message":"too many requests"}{"code": 429,"message":"too many requests"}{"code": 429,"message":"too many requests"}{"code": 429,"message":"too many requests"}{"code": 7209,"message":"captcha required"}
擼主嘗試刷新頁(yè)面,隨便輸了一個(gè)手機(jī)號(hào),再次點(diǎn)擊發(fā)送,提示用戶輸入驗(yàn)證碼,顯然是加強(qiáng)了防備,觸發(fā)了惡意請(qǐng)求認(rèn)證攔截機(jī)制。
安全機(jī)制
對(duì)于開(kāi)發(fā)者來(lái)說(shuō),他們不僅要考慮用戶正常獲取驗(yàn)證碼的體驗(yàn)還要考慮短信接口的安全性,擼主總結(jié)了以下幾點(diǎn),希望對(duì)大家有所幫助。
- 后臺(tái)請(qǐng)求限流,對(duì)單位時(shí)間內(nèi)發(fā)送頻率做限制。
- 驗(yàn)證碼機(jī)制,切記不要一開(kāi)始就限制驗(yàn)證碼,體驗(yàn)及其不友好,觸發(fā)限流以后開(kāi)啟驗(yàn)證碼校驗(yàn)。
- 監(jiān)控日發(fā)送短信數(shù)量,觸發(fā)一定的閾值做相應(yīng)的處理,根據(jù)實(shí)際業(yè)務(wù)需求。
- 驗(yàn)證碼存儲(chǔ)一定要保證key為手機(jī)號(hào),切記不要以其它標(biāo)識(shí)作為key,比如sessionId。
- 一定要設(shè)置驗(yàn)證碼失效時(shí)間,比如五分鐘,或者更短。
- 驗(yàn)證碼盡量保證短小精悍,四到六位即可。
- 如果后臺(tái)不做限制,切記前臺(tái)一定要做個(gè)倒計(jì)時(shí)的限制,至少過(guò)濾一部分小白用戶。
代碼案例
給小伙伴分享一個(gè)簡(jiǎn)單的驗(yàn)證碼生成、存儲(chǔ)、失效代碼案例:
import com.google.common.cache.CacheBuilder;import com.google.common.cache.CacheLoader;import com.google.common.cache.LoadingCache;import java.util.concurrent.ExecutionException;import java.util.concurrent.TimeUnit;public class Mobile { /** * 測(cè)試方便,這里設(shè)置了3秒失效 */ private static LoadingCache<String, String> caches = CacheBuilder.newBuilder() .maximumSize(1000) .expireAfterWrite(3, TimeUnit.SECONDS) .build(new CacheLoader<String, String>() { @Override public String load(String mobile) { return ""; } }); public static void main(String[] args) throws ExecutionException, InterruptedException { Integer code = (int)((Math.random()*9+1)*100000); caches.put("17762018888",code.toString()); System.out.println(caches.get("17762018888")); Thread.sleep(4000); System.out.println("是不是沒(méi)了:"+caches.get("17762018888")); }}
小結(jié)
重要的功能必須進(jìn)行前后端校驗(yàn),必要的時(shí)候一定要做好限流、黑名單等騷操作?。?!
出自:https://blog.52itstyle.vip/archives/5245/
作者:小柒