网站注册页一般会暴露短信接口,从安全角度的考虑应该对短信接口做相应的保护。常见的方式有
1、动态注册验证码:
a、短信可触发条件为短信验证码正确;
b、调用短信接口前再次验证短信验证码;
c、调用短信接口前验证HTTP_Refer;
2、限制IP以及单个手机号的访问次数
策略:每次发送短信后将相关手机号,IP信息以及首次发送的时间已经发送的次数存入Redis,每次发送前 取出Redis中的相关信息 进行比对验证,如果已超过策略则提醒,并且不再接受短信接口的请求调用。每次发送短信后将Redis中的相关信息进行调整,分为首次的非首次。
Redis存储读取代码:
$info['FirstSendTime'] = '第一次发送时间'; $info['haveSendTimes'] = '已经发送的次数'; hset('sms','13112345678',$info) ; $info = hget('sms','13112345678); hset('ip','127.0.0.1',$info); $info = hget('sms','127.0.0.1');
实例:
//一天内 发短信对手机号和IP进行限制 private function SmsCheck($phone){ $sms_config = C('SmsConfig'); // IP限制 $ip_access = $this->_ipLimit($sms_config); //读取Redis手机号的发送次数 $sms_collect = Db_Redis::hget_json('SMS', $phone); // 如果在reids中有数据,则执行策略 empty($sms_collect) || $re = $this->_doStrategy($sms_collect, $sms_config); //通过验证,重新设置策略 $this->_resetStrategy($sms_collect, $ip_access,$phone); } // 重置 $sms redis中保存的短信信息 $ipAccess redis中保存的IP地址信息 private function _resetStrategy($sms = '', $ipAccess = '',$phone){ // 重置IP数据 $this->_resetIp($ipAccess); //如果在redis中无数据,则初始化数据 if ( empty($sms) ) { $sms = $this->_initsms(); } else { // 当前时间 - 第一次发送时间大于24小时,则需重新初始化 if ( ($_SERVER['REQUEST_TIME'] - $sms['firstSendTime']) > 24 * 3600 ) { $sms = $this->_initsms(); } else { // 当前时间 - 第一次发送时间小于24小时,则将发送数量进行相加 $sms['sendNumber']++; } } Db_Redis::hset('SMS', $phone, json_encode($sms)); } //重置IP private function _resetIp($ipAccess = array()) { // IP重置策略 if ( empty($ipAccess) ) { // IP第一次使用 $ipAccess = array( 'firstAccessTime' => $_SERVER['REQUEST_TIME'], 'access_ip_number' => 1 ); } else { # IP非第一次使用,操作时间已经过了24小时 if ( ($_SERVER['REQUEST_TIME'] - $ipAccess['firstAccessTime']) > 24 * 3600 ) { $ipAccess = array( 'firstAccessTime' => $_SERVER['REQUEST_TIME'], 'access_ip_number' => 1 ); } else { // 操作时间未过24小时 $ipAccess['access_ip_number']++; } } Db_Redis::hset('AccessIp',USER_IP, json_encode($ipAccess)); } //充值 短信次数 private function _initsms(){ return array( 'sendNumber' => 1, 'firstSendTime' => $_SERVER['REQUEST_TIME'], ); } //IP限制 private function _ipLimit($config) { # 获取IP地址的访问次数 $access_number = Db_Redis::hget_json('AccessIp', USER_IP); # 如果请求时间 - 第一次访问时间 在24小时内发送短信的数量超过配置数量,则提示短信发送数量已经超额 if ( ($_SERVER['REQUEST_TIME'] - $access_number['firstAccessTime']) < 24 * 3600 ) { if ( $access_number['access_ip_number'] >= $config['ip_max_times'] ) { msg('IP您今天发送的短信已超标,请在24小时后再进行发送'); } } return $access_number; } //执行策略 $collect=> Redis中保存的数据信息 $config=>配置的限制信息 private function _doStrategy($collect,$config) { // 如果在一天内发送的数量超过配置数量,则提示超额发送 if ( ($_SERVER['REQUEST_TIME'] - $collect['firstSendTime']) < 24 * 3600 ) { if ( $collect['sendNumber'] >= $config['phone_max_times'] ) { msg('smg您今天发送的短信已超标,请在24小时后再进行发送'); } } }