短信验证码在目前大多数web应用中都会有,本文介绍一个基于Yii2 Validator方式的验证码验证方式。 在其他文章中看到的方式大多比较难做到一次封装,多次重用。 使用此方式的好处自然不用多说,Validator支持在Model和Form中使用,使用的时候只需要在rules中添加一条验证规则即可。 第一步: 准备数据表,用来存储短信验证码 CREATE TABLE `tbl_sms_log` ( `id` int(11) NOT NULL AUTO_INCREMENT, `to` varchar(20) NOT NULL DEFAULT ‘‘ COMMENT ‘手机号‘, `usage` varchar(20) NOT NULL DEFAULT ‘‘ COMMENT ‘用途‘, `code` varchar(6) DEFAULT NULL COMMENT ‘验证码‘, `result` varchar(80) DEFAULT ‘‘ COMMENT ‘发送结果‘, `error_code` varchar(255) DEFAULT ‘‘ COMMENT ‘错误码‘, `error_msg` varchar(255) DEFAULT ‘‘ COMMENT ‘错误信息‘, `used` tinyint(1) NOT NULL DEFAULT ‘0‘ COMMENT ‘是否使用‘, `use_time` int(11) DEFAULT ‘0‘ COMMENT ‘使用时间‘, `create_time` int(11) DEFAULT ‘0‘ COMMENT ‘发送时间‘, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8; 表结构可根据项目实际场景进行细节调整。 创建好数据表之后, 再使用Gii生成对应的Model类app\models\SmsLog 第二步: 创建短信验证码验证器, app\validators\SmscodeValidator namespace app\validators; use app\models\SmsLog; use yii\validators\Validator; /** * 短信验证码验证器 * Class SmscodeValidator */ class SmscodeValidator extends Validator { /** * 对应Smslog表中的usage字段,用来匹配不同用途的验证码 * @var string sms code type */ public $usage; /** * Model或者form中提交的手机号字段名称 * @var string */ public $phoneAttribute = ‘cellphone‘; /** * 验证码过期时间 * @var int */ public $expireTime = 10800; /** * @param \yii\base\Model $model * @param string $attribute */ public function validateAttribute($model, $attribute) { $fieldName = $this->phoneAttribute; $cellPhone = $model->$fieldName; $smsLog = SmsLog::find()->where([ ‘to‘ => $cellPhone, ‘usage‘ => $this->usage ])->orderBy(‘create_time DESC‘)->one(); /** @var $smsLog SmsLog */ $time = time(); if( is_null($smsLog) || ($smsLog->code != $model->$attribute) || ($smsLog->create_time > $time || $time > ($smsLog->create_time + $this->expireTime) ) ) { $this->addError($model, $attribute,‘验证码有误‘); }else{ $smsLog->used = 1; $smsLog->use_time = $time; $smsLog->save(); } } } 第三步: 使用方法, 在Model或者Form中添加Rules 例如, 在用户注册使用,前端通过ajax请求后台向指定手机号,发送了验证码 在验证的时候只需要添加一条rule: [‘verifyCode‘, ‘\app\validators\SmscodeValidator‘, ‘usage‘ => ‘userRegister‘ ], 完整的rule,可以覆盖SmscodeValidator中的三个属性的值 [‘verifyCode‘, ‘\app\validators\SmscodeValidator‘, ‘usage‘ => ‘userRegister‘, ‘phoneAttribute‘ => ‘手机号字段名称‘, ‘expireTime‘ => ‘短信验证码有效时间‘ ], RegisterForm.php namespace mobile\models; use yii; class RegisterForm extends AjaxForm { const VERCODE_USAGE = ‘userRegister‘; public $cellphone; public $verifyCode; public $password; public function rules() { return [ [[‘cellphone‘, ‘verifyCode‘, ‘password‘], ‘required‘], [‘verifyCode‘, ‘\common\validators\SmscodeValidator‘, ‘usage‘ => self::VERCODE_USAGE ], [‘password‘ , ‘string‘, ‘min‘ => 6, ‘max‘ => 32], [‘cellphone‘, ‘filter‘, ‘filter‘ => ‘trim‘], [‘cellphone‘, ‘match‘, ‘pattern‘=>‘/^1[34578][0-9]{9}$/‘,‘message‘=>‘请输入正确的手机号‘], [‘cellphone‘, ‘unique‘, ‘targetClass‘ => ‘\mobile\models\User‘, ‘message‘ => ‘此手机号已经被注册‘], ]; } /** * 用户注册 * @return User|null */ public function register() { if($this->validate()) { $user = new User(); $user->cellphone = $this->cellphone; $user->username = $this->cellphone; $user->setPassword($this->password); $user->cellphone_verified = 1; $user->create_from = Yii::$app->id; $user->create_ip = Yii::$app->request->getUserIP(); $user->create_time = time(); if($user->save()) { return $user; } } return null; } public function attributeLabels() { return [ ‘truename‘ => ‘真实姓名‘, ‘cellphone‘ => ‘手机号码‘, ‘verifyCode‘ => ‘验证码‘, ‘password‘ => ‘密码‘, ‘repassword‘ => ‘确认密码‘ ]; } } 当然, 首先你得利用自己的方式(比如,前端点击form中按钮,利用Ajax请求后台发送验证码)发送验证码。 本文的主要目的是能让大家能够通过一条rule快捷实现短信验证的目的。
时间: 2024-10-27 04:39:22