「PHP开发APP接口实战013」手机号快速登录一

需求分析

  • 用户使用手机号 + 短信验证码实现快速登录系统
  • 用户不存在,则自动创建用户帐号
  • 每次登录需要更新最后登陆时间
  • 如果配置为单点登陆,则每次登陆都生成一个新的 TOKEN(用户身份标识)
功能流程图

接口地址: http://127.0.0.1:20081/user/login
请求方式: POST

请求参数:
参数名 必选 类型 说明
user_mobile string 手机号
code string 短信验证码
返回示例:
{
    "status": "1",
    "item": {
        "user_token": "fa630cac17ebdfb115e13c3de8857a5a"
    }
}
返回参数说明:
参数名 说明
user_token 用户身份标识

创建接口

  1. /app/controllers 目录下创建控件器文件 UserController.php,添加代码:
<?php
class UserController extends BaseController
{
    /**
     * 用户登陆
     * @throws Exception
     */
    public function loginAction()
    {

        // 验证请求方法是否是POST
        $this->isPost();

    }
}

以上代码,创建了登陆接口,并验证了请求方式必须为 POST。

  1. 打开 /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位数字有效短信验证码
  1. 为控制器 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, BetweenPhalcon 内置验证器,分别验证必填参数,手机号格式, 验证码是否为数字和是否在 10009999 之间(4位数字验证)。
XValidatorCode 为自定议短信验证码验证器。

  1. /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;
    }
  • 检测提交的手机号和验证码是否与缓存数据一致,是否已被验证,是否过期等。
  • 若通过验证,还会将验证在码状态设置为已验证,防止重复使用。
  1. 创建短信验证码自定义验证器,在 /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']

数据库连接

  1. 配置数据库连接参数,打开 /app/config/config.ini, 添加:
[database]
adapter = Mysql
host = localhost
username = root
password = 123456
dbname = demo
charset = utf8
port = 3306
prefix = dm_

请根据自己数据库设置,自行更改对应参数

  1. 创建连接,打开 /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默认属性:

  1. 指定数据库编码为UTF-8
  2. 强制指定列名小写
  3. 将结果集中NULL转换为空字符串
  4. 仅仅返回以键值作为下标的查询的结果集,名称相同的数据只返回一个

经过上面的简单操作,我们就可以在 Controller 中使用 $this->db 或模型来操作数据库了。官方文档

To be continued......

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,384评论 25 707
  • 文章图片上传不正常,如需文档,可联系微信:1017429387 目录 1 安装... 4 1.1 配置探针... ...
    Mrhappy_a7eb阅读 6,276评论 0 5
  • 晨曦日惊陌上桑, 长清一角露锋芒, 并肩行过路与廊 一笔一字斟酌上, 再回首,红了满地霜
    Fiona_v阅读 222评论 0 1
  • 前言 这篇文章主要介绍KVC中的Collection Operators,以及自定义Collection Oper...
    01_Jack阅读 2,631评论 6 23