本文目录导读:

在ThinkPHP项目中实现短信验证码发送,通常需要以下几个步骤:
配置短信服务商
在config/目录下创建短信配置:
// config/sms.php
return [
'default' => 'aliyun',
'drivers' => [
'aliyun' => [
'access_key_id' => 'your-access-key-id',
'access_key_secret' => 'your-access-key-secret',
'sign_name' => '您的签名',
'template_code' => 'SMS_0000000',
],
'tencent' => [
'secret_id' => 'your-secret-id',
'secret_key' => 'your-secret-key',
'sdk_app_id' => 'your-app-id',
'sign_name' => '您的签名',
'template_id' => 'your-template-id',
],
],
];
创建短信发送服务类
// app/service/SmsService.php
namespace app\service;
use think\Config;
use think\facade\Log;
class SmsService
{
protected $config;
public function __construct()
{
$this->config = config('sms.');
}
/**
* 发送验证码
* @param string $phone 手机号
* @return array
*/
public function sendCode($phone)
{
// 生成4位或6位验证码
$code = $this->generateCode(6);
// 存储验证码到缓存(5分钟有效)
cache("sms_code_{$phone}", $code, 300);
// 根据配置选择短信服务商
$result = $this->sendSms($phone, $code);
if ($result['code'] == 1) {
return ['status' => true, 'msg' => '验证码发送成功'];
} else {
cache("sms_code_{$phone}", null);
return ['status' => false, 'msg' => '验证码发送失败'];
}
}
/**
* 发送短信
* @param string $phone
* @param string $code
*/
protected function sendSms($phone, $code)
{
try {
// 使用阿里云短信
return $this->sendByAliyun($phone, $code);
} catch (\Exception $e) {
Log::error('短信发送失败: ' . $e->getMessage());
return ['code' => 0, 'msg' => $e->getMessage()];
}
}
/**
* 阿里云短信
*/
protected function sendByAliyun($phone, $code)
{
$config = $this->config['drivers']['aliyun'];
// 引入阿里云SDK
// 使用 require 引入 aliyun-sdk.php
$params = [
'PhoneNumbers' => $phone,
'SignName' => $config['sign_name'],
'TemplateCode' => $config['template_code'],
'TemplateParam' => json_encode(['code' => $code]),
];
// 此处为伪代码,实际需要根据阿里云SDK进行调用
// $result = \Aliyun\Sms\SendSms::send($config, $params);
// 模拟发送成功
return ['code' => 1];
}
/**
* 生成验证码
* @param int $length
* @return string
*/
protected function generateCode($length = 6)
{
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= rand(0, 9);
}
return $code;
}
/**
* 验证验证码
* @param string $phone
* @param string $code
* @return bool
*/
public function verifyCode($phone, $code)
{
$cachedCode = cache("sms_code_{$phone}");
if ($cachedCode === false || $cachedCode != $code) {
return false;
}
// 验证成功后删除缓存
cache("sms_code_{$phone}", null);
return true;
}
}
创建验证码控制器
// app/controller/Sms.php
namespace app\controller;
use think\Request;
use app\service\SmsService;
use think\facade\Validate;
class Sms
{
protected $smsService;
public function __construct(SmsService $smsService)
{
$this->smsService = $smsService;
}
/**
* 发送验证码
* @param Request $request
*/
public function sendCode(Request $request)
{
// 获取手机号
$phone = $request->post('phone');
// 验证手机号格式
$validate = Validate::rule([
'phone' => 'require|mobile',
]);
if (!$validate->check(['phone' => $phone])) {
return json(['code' => 0, 'msg' => '手机号格式不正确']);
}
// 检查发送频率(60秒内只能发送一次)
$lastSendTime = cache("sms_send_time_{$phone}");
if ($lastSendTime && time() - $lastSendTime < 60) {
return json(['code' => 0, 'msg' => '发送过于频繁,请稍后再试']);
}
// 发送验证码
$result = $this->smsService->sendCode($phone);
if ($result['status']) {
// 记录发送时间
cache("sms_send_time_{$phone}", time(), 300);
return json(['code' => 1, 'msg' => $result['msg']]);
} else {
return json(['code' => 0, 'msg' => $result['msg']]);
}
}
/**
* 验证验证码
* @param Request $request
*/
public function verifyCode(Request $request)
{
$phone = $request->post('phone');
$code = $request->post('code');
if ($this->smsService->verifyCode($phone, $code)) {
return json(['code' => 1, 'msg' => '验证成功']);
} else {
return json(['code' => 0, 'msg' => '验证码错误或已过期']);
}
}
}
路由配置
// route/app.php
use think\facade\Route;
Route::post('sms/send', 'Sms/sendCode');
Route::post('sms/verify', 'Sms/verifyCode');
使用示例
// 前端JS示例
function sendSms() {
const phone = document.getElementById('phone').value;
$.ajax({
url: '/sms/send',
method: 'POST',
data: { phone: phone },
success: function(response) {
if (response.code == 1) {
alert('验证码已发送');
// 开始倒计时
startCountdown();
} else {
alert(response.msg);
}
}
});
}
function startCountdown() {
let seconds = 60;
const timer = setInterval(() => {
seconds--;
if (seconds <= 0) {
clearInterval(timer);
document.getElementById('sendBtn').textContent = '重新发送';
} else {
document.getElementById('sendBtn').textContent = seconds + '秒后重发';
}
}, 1000);
}
安全优化建议
class SmsService
{
// 添加IP限制、设备限制等
protected function checkLimit($phone, $ip)
{
// 使用Redis或缓存记录
$key = "sms_limit_{$phone}";
$count = cache($key) ?: 0;
if ($count >= 5) {
return false; // 当日发送次数过多
}
cache($key, $count + 1, 86400); // 24小时
return true;
}
// 图形验证码保护
protected function needCaptcha($phone)
{
// 判断是否需要图形验证码
$failCount = cache("sms_fail_{$phone}") ?: 0;
return $failCount >= 3;
}
}
注意事项
- 定时清理:定期清理缓存中的验证码
- 日志记录:记录所有发送记录
- 错误处理:合理处理各种异常情况
- 性能考虑:使用缓存存储验证码,避免数据库压力
- 安全防护:防止短信轰炸,添加频率限制
这样可以实现一个完整、安全的短信验证码发送功能,根据实际使用的短信服务商,需要调整具体的SDK调用代码。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播