需求分析
- 用户使用手机号 + 短信验证码实现快速登录系统
- 用户不存在,则自动创建用户帐号
- 每次登录需要更新最后登陆时间
- 如果配置为单点登陆,则每次登陆都生成一个新的 TOKEN(用户身份标识)
接口地址: http://127.0.0.1:20081/user/login
请求方式: POST
请求参数:
参数名 | 必选 | 类型 | 说明 |
---|---|---|---|
user_mobile | 是 | string | 手机号 |
code | 是 | string | 短信验证码 |
返回示例:
{
"status": "1",
"item": {
"user_token": "fa630cac17ebdfb115e13c3de8857a5a"
}
}
返回参数说明:
参数名 | 说明 |
---|---|
user_token | 用户身份标识 |
创建接口
- 在
/app/controllers
目录下创建控件器文件UserController.php
,添加代码:
<?php
class UserController extends BaseController
{
/**
* 用户登陆
* @throws Exception
*/
public function loginAction()
{
// 验证请求方法是否是POST
$this->isPost();
}
}
以上代码,创建了登陆接口,并验证了请求方式必须为 POST。
- 打开
/app/config/config.php
, 在authentication.exclude
添加元素user/login
。将登陆接口排除身份认证。如:
// 身份认证配置
'authentication' => [
'enable' => 1, // 身份认证: 0 关闭, 1 激活
'single' => 0, // 单点登录: 0 允许多个客户端同时登录; 1 同一时间,只请允许最后登录设备使用
// 身份认证排除页面
'exclude' => [
'index/index',
'user/login',
'sms/send',
]
],
请求参数验证
- 手机号必填,且必须为11位有效手机号
- 4位数字有效短信验证码
- 为控制器
UserController
创建验证类XValidationUser
, 并为loginAction()
创建对应的验证函数login()
,如:
// 检测是否为空
use Phalcon\Validation\Validator\PresenceOf;
// 正则表达式验证
use Phalcon\Validation\Validator\Regex;
// 数字字符
use Phalcon\Validation\Validator\Digit;
// 介于二者之间,minimum<=x<=maximum
use Phalcon\Validation\Validator\Between;
/**
*
* 用户参数验证
*/
class XValidationUser
{
/**
* 登录参数验证
* @param $params
* @return bool
* @throws Exception
*/
public static function login($params)
{
$validation = new XValidation();
$validation->add('user_mobile', new PresenceOf(['message' => '缺少手机号码']));
$validation->add('user_mobile', new Regex(['message' => '无效手机号码', 'pattern' => '/^1[34578]{1}\d{9}$/']));
$validation->add('code', new PresenceOf(['message' => '缺少短信验证码']));
$validation->add('code', new Digit(['message' => '无效短信验证码']));
$validation->add('code', new Between(['message' => '无效短信验证码', 'minimum' => 1000, 'maximum' => 9999]));
$validation->add('code', new XValidatorCode(['message' => '无效短信验证码', 'with' => 'user_mobile']));
return $validation->valid($params);
}
}
以上
PresenceOf
,Regex
,Digit
,Between
为Phalcon
内置验证器,分别验证必填参数,手机号格式, 验证码是否为数字和是否在1000
到9999
之间(4位数字验证)。
XValidatorCode
为自定议短信验证码验证器。
- 在
/app/library/SMS.php
中添加函数validate()
,添加以下代码:
/**
* 验证短信验证码
* 只有最后一次发送的验证码才有效
* 验证码有效时间5分钟
* @param $mobile
* @param $code
* @return bool
*/
public function validate($mobile, $code)
{
$codes = $this->getCacheCodes($mobile);
if (count($codes) == 0) {
return false;
}
$lastCode = end($codes);
// 只有最后一次发送的验证码才有效
if ($lastCode['code'] != $code) {
return false;
}
// 验证码有效时间5分钟
if ($this->config['valid_time'] > 0 && time() - $lastCode['time'] > $this->config['valid_time']) {
return false;
}
// 验证码已被验证,自动失效
if (isset($lastCode['verified']) && $lastCode['verified'] == 1) {
return false;
}
// 通过验证后,将验证在码状态设置为已验证
$codes[count($codes) - 1]['verified'] = 1;
// 更新缓存
XMemcache::instance('sms')->set($mobile, $codes);
return true;
}
- 检测提交的手机号和验证码是否与缓存数据一致,是否已被验证,是否过期等。
- 若通过验证,还会将验证在码状态设置为已验证,防止重复使用。
- 创建短信验证码自定义验证器,在
/app/library/
目录中新建XValidatorCode.php
文件, 插入代码 :
<?php
use Phalcon\Validation,
Phalcon\Validation\Validator,
Phalcon\Validation\ValidatorInterface,
Phalcon\Validation\Message;
class XValidatorCode extends Validator implements ValidatorInterface
{
/**
* @param Validation $validation
* @param $attribute
* @return bool
*/
public function validate(Validation $validation, $attribute)
{
$value = $validation->getValue($attribute);
$mobile = $validation->getValue($this->getOption('with'));
if (!SMS::instance()->validate($mobile, $value)) {
$message = $this->getOption('message');
if (!$message) {
$message = '短信验证码错误';
}
$validation->appendMessage(new Message($message, $attribute, 'Code'));
return false;
}
return true;
}
}
调用方法:
new XValidatorCode(['message' => '无效短信验证码', 'with' => 'user_mobile']
,
数据库连接
- 配置数据库连接参数,打开
/app/config/config.ini
, 添加:
[database]
adapter = Mysql
host = localhost
username = root
password = 123456
dbname = demo
charset = utf8
port = 3306
prefix = dm_
请根据自己数据库设置,自行更改对应参数
- 创建连接,打开
/app/public/index.php
, 找到$di = new Phalcon\Di\FactoryDefault();
, 在下面添加以下代码:
// 设置数据库服务
$di->set(
"db",
function () {
$config = Config::instance()->get('database', 'ini');
$config['options'] = [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'",
PDO::ATTR_CASE => PDO::CASE_LOWER, // 强制列名小写。
PDO::ATTR_ORACLE_NULLS => PDO::NULL_TO_STRING, // 将 NULL 转换成空字符串。
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 仅仅返回以键值作为下标的查询的结果集,名称相同的数据只返回一个。
];
return new \Phalcon\Db\Adapter\Pdo\Mysql($config);
}
);
设置数据库服务, 并设置PDO默认属性:
- 指定数据库编码为UTF-8
- 强制指定列名小写
- 将结果集中NULL转换为空字符串
- 仅仅返回以键值作为下标的查询的结果集,名称相同的数据只返回一个
经过上面的简单操作,我们就可以在 Controller
中使用 $this->db
或模型来操作数据库了。官方文档
To be continued......