Yii2在Form中处理短信验证码的Validator,耦合度最低的短信验证码验证方式

短信验证码在目前大多数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

Yii2在Form中处理短信验证码的Validator,耦合度最低的短信验证码验证方式的相关文章

iOS中打电话、打开网址、发邮件、发短信等

常用小功能 小功能简介 iOS中的很多小功能都是非常简单的,几行代码就搞定了,比如打电话.打开网址.发邮件.发短信等 打电话-方法1 最简单最直接的方式:直接跳到拨号界面 NSURL *url = [NSURL URLWithString:@"tel://10010"]; [[UIApplication sharedApplication] openURL:url]; 缺点 电话打完后,不会自动回到原应用,直接停留在通话记录界面 打电话-方法2 拨号之前会弹框询问用户是否拨号,拨完后能

jquery中form中使用submit出现的问题,未解决

$("#login_btn").click(function(){在type为submit的按钮下 if($("#id_password").val().length == 0){//检验密码是否为空 $('form').submit(function(){ alert("1") return false; }); }else if($("#vali").val() != code){//验证码是否正确 $('form').s

Android短信的发送和广播接收者实现短信的监听

原文地址:http://www.cnblogs.com/zyw-205520/archive/2013/01/24/2875686.html Android短信的发送和广播接收者实现短信的监听  要注意Android清单中权限的设置以及广播的注册监听实现 以下就是 Android清单的XML AndroidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" packag

Android短信监听(三)——利用Loader实现短信监听

MainActivity如下: package cc.c; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Loader; import android.database.Curs

Android短信监听(二)——利用ContentObserver实现短信监听

MainActivity如下: package cc.testsmslistener; import cc.testsmslistener.SMSContentObserver.MessageListener; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.app.Activity; /** *

Android短信监听(一)——利用BroadcastReceiver实现短信监听

MainActivity如下: package cc.testsmsbroadcastreceiver; import cc.testsmsbroadcastreceiver.SMSBroadcastReceiver.MessageListener; import android.os.Bundle; import android.widget.TextView; import android.app.Activity; /** * Demo描述: * 利用BroadcastReceiver实现

【Nodejs项目手记】Nodejs中使用图片验证码,captchapng模块可以解决Nodejs图片验证码

Nodejs项目,在做图片验证码的时候遇到了难题.Nodejs没有图片库,以后会有,但是现在没有. 网络上搜索一圈,有几个解决方案: 1.采用第三方验证码程序,有的时候,项目可能不允许: 2.使用Java或者PHP生成图片,Nodejs调用,中间采用Redies共享: 这两种方式都不太理想,好在终于找到了可以支持Nodejs图片验证码的一个库,虽然只支持数字,但是也还不错.原理是使用Base64的图片编码方式. 这个库的Gighub地址是:https://github.com/GeorgeCha

form 中Enctype=multipart/form-data 的作用

ENCTYPE="multipart/form-data"用于表单里有图片上传. <form name="userInfo" method="post" action="first_submit.jsp"    ENCTYPE="multipart/form-data">表单标签中设置enctype="multipart/form-data"来确保匿名上载文件的正确编码. 如

HTML 之 Web页面表单form中只有一个input的text元素,按回车默认提交

WEB开发中,如果页面的 form 中只有一个input元素,在该input元素的输入框中按回车(注:此时并没有写对应的onkeydown等事件处理),则浏览器会默认提交表单,请看如下代码: <html> <head> <title>页面中只有一个input元素时默认提交表单</title> </head> <body> <form action="http://www.baidu.com" name=&qu