核心思路
无论采用哪种方案,其核心流程都大同小异:

(图片来源网络,侵删)
- 用户输入手机号:在登录页面,除了用户名和密码,增加一个“手机号”输入框。
- 获取验证码:用户输入手机号后,点击“获取验证码”按钮。
- 后端处理:
- 验证手机号:检查该手机号是否已经绑定到某个账户。
- 生成验证码:生成一个随机数字(如4位或6位)。
- 发送验证码:调用短信平台API,将验证码发送到用户手机。
- 存储验证码:将验证码和手机号、过期时间等信息存入数据库或缓存(如Redis),并设置一个短暂的过期时间(通常为5分钟)。
- 用户输入验证码:用户收到短信后,将验证码填入登录表单。
- 后端校验:
- 用户提交登录表单(包含用户名、密码、手机号、验证码)。
- 系统首先校验用户名和密码是否正确。
- 然后校验用户输入的验证码与数据库/缓存中存储的验证码是否一致,以及是否过期。
- 全部通过后,允许用户登录。
修改现有登录文件(推荐,适合有一定开发能力者)
这是最直接的方法,但需要修改核心文件,升级时可能需要重新修改。
第1步:修改登录模板文件 (/templets/default/login.htm)
- 找到用户名和密码的输入框。
- 在它们旁边或下方,添加手机号和验证码的输入框,以及一个“获取验证码”的按钮。
示例代码:
<div class="row">
<input type="text" name="userid" id="userid" placeholder="用户名/手机号" />
</div>
<div class="row">
<input type="password" name="pwd" id="pwd" placeholder="密码" />
</div>
<!-- 新增部分开始 -->
<div class="row">
<input type="text" name="mobile" id="mobile" placeholder="请输入绑定的手机号" />
</div>
<div class="row">
<div style="display: flex;">
<input type="text" name="code" id="code" placeholder="短信验证码" style="flex: 1;" />
<button type="button" id="get-code-btn" style="width: 120px; margin-left: 10px;">获取验证码</button>
</div>
</div>
<!-- 新增部分结束 -->
<div class="row">
<button type="submit" class="btn-login">登 录</button>
</div>
第2步:创建发送验证码的接口文件 (/member/sendcode.php)
这个文件将处理AJAX请求,用于生成并发送验证码。
<?php
require_once(dirname(__FILE__)."/config.php");
require_once(DEDEINC."/datalistcp.class.php");
require_once(DEDEINC."/userlogin.class.php");
require_once(DEDEINC."/sms/sms.php"); // 假设你有一个短信发送类
// 1. 获取前端传来的手机号
$mobile = isset($mobile) ? trim($mobile) : '';
// 2. 验证手机号格式
if(!preg_match("/^1[3-9]\d{9}$/", $mobile)){
echo json_encode(array('code' => 0, 'msg' => '手机号格式不正确'));
exit;
}
// 3. 检查手机号是否已绑定某个用户
$dsql = new DedeSql(false);
$row = $dsql->GetOne("SELECT userid FROM `#@__member` WHERE mobile='{$mobile}'");
if(!is_array($row)){
echo json_encode(array('code' => 0, 'msg' => '该手机号尚未绑定任何账户'));
exit;
}
// 4. 生成随机验证码
$code = rand(100000, 999999); // 6位验证码
// 5. 调用短信接口发送验证码
// !! 这里需要替换成你自己的短信平台API !!
$sms = new Sms(); // 假设这个类已经配置好
$result = $sms->send($mobile, "您的验证码是:{$code},5分钟内有效。");
// 6. 存储验证码到数据库或缓存(这里以数据库为例)
// 创建一个临时表来存储验证码,如果没有就创建一个
$table_name = $GLOBALS['cfg_dbprefix'].'sms_verify_code';
$dsql->ExecNoneQuery("CREATE TABLE IF NOT EXISTS `{$table_name}` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`mobile` varchar(20) NOT NULL,
`code` varchar(10) NOT NULL,
`create_time` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `mobile` (`mobile`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
// 删除该手机旧的验证码记录
$dsql->ExecNoneQuery("DELETE FROM `{$table_name}` WHERE mobile='{$mobile}'");
// 插入新的验证码记录
$dsql->ExecuteNoneQuery("INSERT INTO `{$table_name}` (`mobile`, `code`, `create_time`) VALUES ('{$mobile}', '{$code}', ".time().")");
// 7. 返回结果
if($result === true){
echo json_encode(array('code' => 1, 'msg' => '验证码发送成功'));
} else {
echo json_encode(array('code' => 0, 'msg' => '验证码发送失败:'.$result));
}
exit;
?>
第3步:修改登录处理文件 (/member/index_do.php)
这是最关键的一步,需要在这里加入验证码的校验逻辑。

(图片来源网络,侵删)
// ... 原有代码 ...
$uid = $username;
$pwd = $password;
// 新增:获取表单提交的手机号和验证码
$mobile = isset($mobile) ? trim($mobile) : '';
$code = isset($code) ? trim($code) : '';
// 新增:校验验证码
if(empty($mobile) || empty($code)){
ShowMsg('请输入手机号和验证码', '-1');
exit();
}
$table_name = $GLOBALS['cfg_dbprefix'].'sms_verify_code';
$dsql = new DedeSql(false);
// 查询数据库中的验证码
$row = $dsql->GetOne("SELECT code, create_time FROM `{$table_name}` WHERE mobile='{$mobile}'");
if(!is_array($row) || $row['code'] != $code){
ShowMsg('验证码错误', '-1');
exit();
}
// 检查验证码是否过期 (例如5分钟)
if(time() - $row['create_time'] > 300){
ShowMsg('验证码已过期,请重新获取', '-1');
exit();
}
// 验证码正确,删除数据库中的记录,防止重复使用
$dsql->ExecNoneQuery("DELETE FROM `{$table_name}` WHERE mobile='{$mobile}'");
// ... 原有的登录逻辑从这里开始 ...
// 即检查用户名密码是否正确,然后进行登录操作
第4步:编写前端JavaScript
为“获取验证码”按钮添加点击事件,调用 /member/sendcode.php 接口。
document.getElementById('get-code-btn').addEventListener('click', function() {
const mobile = document.getElementById('mobile').value;
const btn = this;
if (!mobile) {
alert('请先输入手机号');
return;
}
// 禁用按钮,防止重复点击
btn.disabled = true;
btn.textContent = '发送中...';
// 发送AJAX请求
fetch('/member/sendcode.php?mobile=' + encodeURIComponent(mobile))
.then(response => response.json())
.then(data => {
if (data.code === 1) {
alert(data.msg);
// 开始倒计时
let countdown = 60;
const timer = setInterval(() => {
btn.textContent = `重新发送(${countdown}s)`;
countdown--;
if (countdown < 0) {
clearInterval(timer);
btn.disabled = false;
btn.textContent = '获取验证码';
}
}, 1000);
} else {
alert(data.msg);
btn.disabled = false;
btn.textContent = '获取验证码';
}
})
.catch(error => {
console.error('Error:', error);
alert('发送失败,请稍后重试');
btn.disabled = false;
btn.textContent = '获取验证码';
});
});
使用第三方插件或模块(最简单,适合新手)
这是最省事的方法,有经验的开发者已经封装好了功能,你只需要下载、安装、配置即可。
-
寻找插件:
- 访问DedeCMS官方论坛、插件市场或知名的DedeCMS资源网站(如织梦吧、DedeCms58等)。
- 搜索关键词如:
DedeCMS 登录验证码、DedeCMS 手机短信登录、DedeCMS 短信接口。
-
选择插件:
(图片来源网络,侵删)- 选择一个评价好、更新及时、文档清晰的插件。
- 注意插件是否支持你当前的DedeCMS版本(如DedeCMS V5.7/V5.8/V6.0等)。
-
安装和配置:
- 通常插件会提供详细的安装说明,一般包括:
- 上传文件到指定目录。
- 执行SQL语句(用于创建数据表或修改配置表)。
- 修改模板文件(方案一中的第1步)。
- 在后台配置短信平台的API Key、Secret等信息。
- 关键配置:你需要先在短信平台(如阿里云短信、腾讯云短信、SendCloud等)注册账号,获取API接口信息,然后在插件的后台配置中填入。
- 通常插件会提供详细的安装说明,一般包括:
-
优缺点:
- 优点:快速、简单,无需编写代码,安全性通常有保障。
- 缺点:可能需要付费购买,或者插件作者不再维护,存在兼容性风险。
重要注意事项
-
短信平台选择:
- 不要使用免费的短信服务,它们通常不稳定,且容易被滥用。
- 推荐使用国内主流的云服务商短信服务,如阿里云短信、腾讯云短信,它们稳定可靠,价格也相对合理。
-
验证码安全:
- 切勿将验证码明文存储在数据库中,应该对验证码进行哈希(如MD5或SHA256)后再存储,即使数据库泄露,攻击者也无法直接获取验证码。
- 验证码必须有有效期(如5分钟),并且使用一次后立即失效。
-
防止恶意请求:
在发送验证码的接口中,增加对同一手机号发送频率的限制,同一个手机号每分钟只能请求一次,每天最多请求10次,这可以有效防止短信轰炸攻击。
-
升级风险:
- 如果采用方案一修改核心文件,那么在未来升级DedeCMS时,这些修改可能会被覆盖,导致功能失效,升级后需要重新进行修改,建议将修改的文件和代码备份好。
-
用户体验:
- 在“获取验证码”按钮上实现倒计时功能,防止用户重复点击。
- 提供清晰的错误提示,如“手机号未注册”、“验证码错误”、“验证码已过期”等。
- 如果您是开发者,且想深度定制,选择方案一,它能让你完全掌控代码逻辑。
- 如果您是网站管理员,对代码不熟悉,强烈推荐方案二,寻找一个成熟的插件,这是最快、最安全、最省心的方式。
希望这份详细的指南能帮助您成功在DedeCMS中实现登录手机验证码功能!
