本文目录导读:

我来帮你实现一个完整的PHP手机号验证码登录系统,这个系统包含后端API和前端演示页面。
数据库设计
-- 用户表 CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `phone` varchar(20) NOT NULL COMMENT '手机号', `password` varchar(255) DEFAULT NULL COMMENT '密码(可选)', `nickname` varchar(50) DEFAULT NULL, `avatar` varchar(255) DEFAULT NULL, `status` tinyint(1) DEFAULT '1' COMMENT '状态:1启用 0禁用', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_phone` (`phone`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 验证码表 CREATE TABLE `sms_codes` ( `id` int(11) NOT NULL AUTO_INCREMENT, `phone` varchar(20) NOT NULL COMMENT '手机号', `code` varchar(6) NOT NULL COMMENT '验证码', `expire_time` datetime NOT NULL COMMENT '过期时间', `ip` varchar(50) DEFAULT NULL COMMENT 'IP地址', `used` tinyint(1) DEFAULT '0' COMMENT '是否已使用', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_phone` (`phone`), KEY `idx_created` (`created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
后端PHP代码
config.php - 配置文件
<?php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASS', '');
// 短信配置(示例使用阿里云短信)
define('ALIYUN_SMS_ACCESS_KEY_ID', 'your_access_key_id');
define('ALIYUN_SMS_ACCESS_KEY_SECRET', 'your_access_key_secret');
define('ALIYUN_SMS_SIGN_NAME', '你的签名');
define('ALIYUN_SMS_TEMPLATE_CODE', 'SMS_123456789'); // 验证码模板
// Session配置
session_start();
// 数据库连接
function db_connect() {
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4",
DB_USER,
DB_PASS
);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
} catch (PDOException $e) {
die('数据库连接失败: ' . $e->getMessage());
}
}
?>
send_sms.php - 发送验证码
<?php
require_once 'config.php';
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['code' => 405, 'msg' => '请求方法不允许']);
exit;
}
$phone = $_POST['phone'] ?? '';
// 验证手机号格式
if (!preg_match('/^1[3-9]\d{9}$/', $phone)) {
echo json_encode(['code' => 400, 'msg' => '手机号格式不正确']);
exit;
}
// 检查发送频率(同一手机号60秒内只能发一次)
$pdo = db_connect();
$stmt = $pdo->prepare("SELECT * FROM sms_codes WHERE phone = ? AND created_at > DATE_SUB(NOW(), INTERVAL 60 SECOND) ORDER BY id DESC LIMIT 1");
$stmt->execute([$phone]);
if ($stmt->fetch()) {
echo json_encode(['code' => 429, 'msg' => '发送太频繁,请稍后再试']);
exit;
}
// 检查IP发送频率(同一IP 24小时内最多发10次)
$ip = $_SERVER['REMOTE_ADDR'];
$stmt = $pdo->prepare("SELECT COUNT(*) FROM sms_codes WHERE ip = ? AND created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)");
$stmt->execute([$ip]);
if ($stmt->fetchColumn() >= 10) {
echo json_encode(['code' => 429, 'msg' => '今日发送次数已达上限']);
exit;
}
// 生成6位随机验证码
$code = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);
// 保存验证码到数据库(有效时间5分钟)
$expire_time = date('Y-m-d H:i:s', time() + 300);
$stmt = $pdo->prepare("INSERT INTO sms_codes (phone, code, expire_time, ip) VALUES (?, ?, ?, ?)");
$stmt->execute([$phone, $code, $expire_time, $ip]);
// 发送短信(使用阿里云短信服务)
$result = sendSms($phone, $code);
if ($result['status']) {
echo json_encode(['code' => 200, 'msg' => '验证码发送成功']);
} else {
echo json_encode(['code' => 500, 'msg' => '验证码发送失败']);
}
/**
* 发送短信函数(阿里云短信)
*/
function sendSms($phone, $code) {
// 这里实现阿里云短信发送
// 首先需要引入阿里云SDK
// 为了演示,这里返回成功(实际开发时替换为真实短信服务)
try {
// 实际代码示例:
/*
$accessKeyId = ALIYUN_SMS_ACCESS_KEY_ID;
$accessKeySecret = ALIYUN_SMS_ACCESS_KEY_SECRET;
// 引入阿里云短信SDK
// require_once 'aliyun-php-sdk/aliyun-php-sdk-core/Config.php';
// require_once 'aliyun-php-sdk/aliyun-php-sdk-core/Profile/DefaultProfile.php';
// require_once 'aliyun-php-sdk/aliyun-php-sdk-core/DefaultAcsClient.php';
// $profile = DefaultProfile::getProfile("cn-hangzhou", $accessKeyId, $accessKeySecret);
// $client = new DefaultAcsClient($profile);
// $request = new Dysmsapi\Request\V20170525\SendSmsRequest();
// $request->setPhoneNumbers($phone);
// $request->setSignName(ALIYUN_SMS_SIGN_NAME);
// $request->setTemplateCode(ALIYUN_SMS_TEMPLATE_CODE);
// $request->setTemplateParam(json_encode(['code' => $code]));
// $response = $client->getAcsResponse($request);
// return ['status' => true, 'message' => '发送成功'];
*/
// 演示环境直接返回成功
return ['status' => true, 'message' => '模拟发送成功'];
} catch (Exception $e) {
return ['status' => false, 'message' => $e->getMessage()];
}
}
?>
verify_code.php - 验证验证码
<?php
require_once 'config.php';
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['code' => 405, 'msg' => '请求方法不允许']);
exit;
}
$phone = $_POST['phone'] ?? '';
$code = $_POST['code'] ?? '';
// 验证输入
if (empty($phone) || empty($code)) {
echo json_encode(['code' => 400, 'msg' => '请填写手机号和验证码']);
exit;
}
$pdo = db_connect();
// 查询最新的验证码
$stmt = $pdo->prepare("
SELECT * FROM sms_codes
WHERE phone = ? AND used = 0
ORDER BY id DESC LIMIT 1
");
$stmt->execute([$phone]);
$sms_data = $stmt->fetch(PDO::FETCH_ASSOC);
// 验证验证码
if (!$sms_data) {
echo json_encode(['code' => 400, 'msg' => '验证码不存在,请重新获取']);
exit;
}
if (strtotime($sms_data['expire_time']) < time()) {
echo json_encode(['code' => 400, 'msg' => '验证码已过期,请重新获取']);
exit;
}
if ($sms_data['code'] !== $code) {
echo json_encode(['code' => 400, 'msg' => '验证码错误']);
exit;
}
// 标记验证码已使用
$stmt = $pdo->prepare("UPDATE sms_codes SET used = 1 WHERE id = ?");
$stmt->execute([$sms_data['id']]);
// 检查用户是否存在,不存在则自动注册
$stmt = $pdo->prepare("SELECT * FROM users WHERE phone = ?");
$stmt->execute([$phone]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) {
// 自动注册新用户
$stmt = $pdo->prepare("INSERT INTO users (phone, nickname) VALUES (?, ?)");
$stmt->execute([$phone, '用户' . substr($phone, -4)]);
$user_id = $pdo->lastInsertId();
} else {
$user_id = $user['id'];
// 检查用户状态
if ($user['status'] == 0) {
echo json_encode(['code' => 403, 'msg' => '账号已被禁用']);
exit;
}
}
// 更新用户登录信息(这里需要token机制)
$token = bin2hex(random_bytes(32));
$_SESSION['user_id'] = $user_id;
$_SESSION['phone'] = $phone;
$_SESSION['token'] = $token;
echo json_encode([
'code' => 200,
'msg' => '登录成功',
'data' => [
'user_id' => $user_id,
'phone' => $phone,
'token' => $token,
'nickname' => $user['nickname'] ?? '新用户'
]
]);
?>
login_api.php - 登录接口(整合版)
<?php
require_once 'config.php';
header('Content-Type: application/json');
$action = $_GET['action'] ?? '';
$method = $_SERVER['REQUEST_METHOD'];
switch ($action) {
case 'send_code':
if ($method !== 'POST') {
echo json_encode(['code' => 405, 'msg' => 'Method Not Allowed']);
break;
}
$phone = $_POST['phone'] ?? '';
// 验证手机号
if (!preg_match('/^1[3-9]\d{9}$/', $phone)) {
echo json_encode(['code' => 400, 'msg' => '手机号格式不正确']);
break;
}
// 生成验证码
$code = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);
// 检查是否频繁发送
$pdo = db_connect();
$stmt = $pdo->prepare("SELECT COUNT(*) FROM sms_codes WHERE phone = ? AND created_at > DATE_SUB(NOW(), INTERVAL 60 SECOND)");
$stmt->execute([$phone]);
if ($stmt->fetchColumn() > 0) {
echo json_encode(['code' => 429, 'msg' => '发送太频繁,请1分钟后再试']);
break;
}
// 保存验证码
$expire_at = date('Y-m-d H:i:s', time() + 300); // 5分钟有效
$stmt = $pdo->prepare("INSERT INTO sms_codes (phone, code, expire_time) VALUES (?, ?, ?)");
$stmt->execute([$phone, $code, $expire_at]);
// 调用短信服务(此处替换为真实短信服务)
$sms_sent = sendSmsCode($phone, $code);
if ($sms_sent) {
echo json_encode(['code' => 200, 'msg' => '验证码发送成功', 'debug_code' => $code]);
} else {
echo json_encode(['code' => 500, 'msg' => '短信发送失败']);
}
break;
case 'login':
if ($method !== 'POST') {
echo json_encode(['code' => 405, 'msg' => 'Method Not Allowed']);
break;
}
$phone = $_POST['phone'] ?? '';
$code = $_POST['code'] ?? '';
if (empty($phone) || empty($code)) {
echo json_encode(['code' => 400, 'msg' => '手机号和验证码不能为空']);
break;
}
// 验证验证码(5分钟内有效,且只能使用一次)
$pdo = db_connect();
$stmt = $pdo->prepare("
SELECT * FROM sms_codes
WHERE phone = ? AND used = 0
AND expire_time > NOW()
ORDER BY id DESC LIMIT 1
");
$stmt->execute([$phone]);
$sms = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$sms || $sms['code'] !== $code) {
echo json_encode(['code' => 400, 'msg' => '验证码无效或已过期']);
break;
}
// 标记验证码已使用
$stmt = $pdo->prepare("UPDATE sms_codes SET used = 1 WHERE id = ?");
$stmt->execute([$sms['id']]);
// 查找或创建用户
$stmt = $pdo->prepare("SELECT * FROM users WHERE phone = ?");
$stmt->execute([$phone]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) {
// 注册新用户
$stmt = $pdo->prepare("INSERT INTO users (phone, nickname) VALUES (?, ?)");
$nickname = '用户' . substr($phone, -4);
$stmt->execute([$phone, $nickname]);
$userId = $pdo->lastInsertId();
$user = [
'id' => $userId,
'phone' => $phone,
'nickname' => $nickname
];
}
// 生成登录token
$token = bin2hex(random_bytes(32));
$_SESSION['user_id'] = $user['id'];
$_SESSION['token'] = $token;
echo json_encode([
'code' => 200,
'msg' => '登录成功',
'data' => [
'user_id' => $user['id'],
'phone' => $user['phone'],
'nickname' => $user['nickname'],
'token' => $token
]
]);
break;
case 'check_login':
// 检查登录状态
session_start();
if (isset($_SESSION['user_id'])) {
echo json_encode([
'code' => 200,
'data' => [
'user_id' => $_SESSION['user_id'],
'phone' => $_SESSION['phone'] ?? ''
]
]);
} else {
echo json_encode(['code' => 401, 'msg' => '未登录']);
}
break;
case 'logout':
session_start();
session_destroy();
echo json_encode(['code' => 200, 'msg' => '退出成功']);
break;
default:
echo json_encode(['code' => 404, 'msg' => '接口不存在']);
}
前端演示页面
login.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">手机号验证码登录</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
background: white;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
padding: 40px;
width: 100%;
max-width: 400px;
}
h2 {
text-align: center;
margin-bottom: 30px;
color: #333;
font-size: 24px;
font-weight: 500;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
font-size: 14px;
font-weight: 500;
}
input[type="tel"] {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
transition: border-color 0.3s;
}
input[type="tel"]:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.input-group {
display: flex;
gap: 10px;
}
.input-group input {
flex: 1;
}
.btn-send-code {
background: #f0f0f0;
border: 1px solid #ddd;
border-radius: 6px;
color: #333;
cursor: pointer;
font-size: 14px;
padding: 12px 16px;
white-space: nowrap;
transition: all 0.3s;
min-width: 130px;
}
.btn-send-code:hover:not(:disabled) {
background: #e0e0e0;
}
.btn-send-code:disabled {
color: #999;
cursor: not-allowed;
background: #f5f5f5;
}
.btn-login {
width: 100%;
padding: 12px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 6px;
color: white;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: opacity 0.3s;
margin-top: 10px;
}
.btn-login:hover:not(:disabled) {
opacity: 0.9;
}
.btn-login:disabled {
background: #cccccc;
cursor: not-allowed;
}
#message {
text-align: center;
margin-top: 15px;
font-size: 14px;
min-height: 20px;
}
.success {
color: #4CAF50;
}
.error {
color: #f44336;
}
.error-message {
color: #f44336;
font-size: 12px;
margin-top: 5px;
min-height: 16px;
}
.login-info {
margin-top: 20px;
padding: 15px;
background: #f8f9fa;
border-radius: 6px;
text-align: center;
color: #555;
}
</style>
</head>
<body>
<div class="login-container">
<h2>手机号登录</h2>
<div class="form-group">
<label for="phone">手机号</label>
<input type="tel" id="phone" placeholder="请输入手机号" maxlength="11">
<div class="error-message" id="phoneError"></div>
</div>
<div class="form-group">
<label for="code">验证码</label>
<div class="input-group">
<input type="text" id="code" placeholder="请输入验证码" maxlength="6">
<button class="btn-send-code" id="sendCodeBtn" onclick="sendCode()">获取验证码</button>
</div>
<div class="error-message" id="codeError"></div>
</div>
<button class="btn-login" id="loginBtn" onclick="login()">登录</button>
<div id="message"></div>
<div class="login-info" id="loginInfo" style="display: none;">
<p>✅ 登录成功!</p>
<p id="userInfo"></p>
<button class="btn-login" style="background: #f44336; margin-top: 10px;" onclick="logout()">退出登录</button>
</div>
</div>
<script>
let countdown = 0;
let timer = null;
// 发送验证码
async function sendCode() {
const phone = document.getElementById('phone').value.trim();
const phoneError = document.getElementById('phoneError');
const sendBtn = document.getElementById('sendCodeBtn');
// 清空错误信息
phoneError.textContent = '';
// 验证手机号
if (!phone) {
phoneError.textContent = '请输入手机号';
return;
}
if (!/^1[3-9]\d{9}$/.test(phone)) {
phoneError.textContent = '手机号格式不正确';
return;
}
// 禁用按钮
sendBtn.disabled = true;
sendBtn.textContent = '发送中...';
try {
const response = await fetch('login_api.php?action=send_code', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `phone=${phone}`
});
const data = await response.json();
if (data.code === 200) {
showMessage('验证码发送成功!', 'success');
// 开始倒计时
startCountdown(sendBtn);
// 开发调试用,实际生产环境不要输出
if (data.debug_code) {
console.log('开发环境验证码:', data.debug_code);
// 自动填入验证码,方便调试
document.getElementById('code').value = data.debug_code;
}
} else {
showMessage(data.msg || '发送失败', 'error');
sendBtn.disabled = false;
sendBtn.textContent = '获取验证码';
}
} catch (error) {
showMessage('网络错误,请稍后再试', 'error');
sendBtn.disabled = false;
sendBtn.textContent = '获取验证码';
}
}
// 登录
async function login() {
const phone = document.getElementById('phone').value.trim();
const code = document.getElementById('code').value.trim();
const phoneError = document.getElementById('phoneError');
const codeError = document.getElementById('codeError');
const loginBtn = document.getElementById('loginBtn');
// 清空错误信息
phoneError.textContent = '';
codeError.textContent = '';
// 验证表单
if (!phone) {
phoneError.textContent = '请输入手机号';
return;
}
if (!/^1[3-9]\d{9}$/.test(phone)) {
phoneError.textContent = '手机号格式不正确';
return;
}
if (!code || code.length !== 6) {
codeError.textContent = '请输入6位验证码';
return;
}
// 禁用登录按钮
loginBtn.disabled = true;
loginBtn.textContent = '登录中...';
try {
const response = await fetch('login_api.php?action=login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `phone=${phone}&code=${code}`
});
const result = await response.json();
if (result.code === 200) {
showMessage('登录成功!', 'success');
// 显示登录成功信息
document.getElementById('loginInfo').style.display = 'block';
document.getElementById('userInfo').textContent =
`用户ID: ${result.data.user_id} | 手机号: ${result.data.phone} | 昵称: ${result.data.nickname}`;
// 保存token到localStorage
localStorage.setItem('token', result.data.token);
// 隐藏登录表单
setTimeout(() => {
document.querySelector('.form-group').style.display = 'none';
document.getElementById('sendCodeBtn').style.display = 'none';
document.getElementById('loginBtn').style.display = 'none';
}, 500);
} else {
showMessage(result.msg || '登录失败', 'error');
}
} catch (error) {
showMessage('网络错误,请稍后再试', 'error');
} finally {
loginBtn.disabled = false;
loginBtn.textContent = '登录';
}
}
// 退出登录
function logout() {
fetch('login_api.php?action=logout')
.then(response => response.json())
.then(data => {
if (data.code === 200) {
localStorage.removeItem('token');
location.reload();
}
});
}
// 倒计时
function startCountdown(btn) {
countdown = 60;
timer = setInterval(() => {
countdown--;
if (countdown <= 0) {
clearInterval(timer);
btn.disabled = false;
btn.textContent = '获取验证码';
} else {
btn.textContent = countdown + 's后重发';
}
}, 1000);
}
// 显示消息
function showMessage(msg, type) {
const messageEl = document.getElementById('message');
messageEl.textContent = msg;
messageEl.className = type;
// 3秒后清除消息
setTimeout(() => {
messageEl.textContent = '';
messageEl.className = '';
}, 3000);
}
// 实时验证手机号格式
document.getElementById('phone').addEventListener('input', function(e) {
const phone = e.target.value.replace(/\D/g, '');
e.target.value = phone;
if (phone.length === 11 && !/^1[3-9]\d{9}$/.test(phone)) {
document.getElementById('phoneError').textContent = '手机号格式不正确';
} else {
document.getElementById('phoneError').textContent = '';
}
});
// 验证码只能输入数字
document.getElementById('code').addEventListener('input', function(e) {
e.target.value = e.target.value.replace(/\D/g, '');
});
// 检查登录状态
window.onload = function() {
const token = localStorage.getItem('token');
if (token) {
fetch('login_api.php?action=check_login')
.then(response => response.json())
.then(data => {
if (data.code === 200 && data.data) {
// 自动登录
document.getElementById('loginInfo').style.display = 'block';
document.getElementById('userInfo').textContent =
`用户ID: ${data.data.user_id} | 手机号: ${data.data.phone}`;
document.querySelector('.form-group').style.display = 'none';
document.getElementById('sendCodeBtn').style.display = 'none';
document.getElementById('loginBtn').style.display = 'none';
}
});
}
};
</script>
</body>
</html>
优化建议
安全增强 (security.php)
<?php
// 添加安全相关的类和函数
class Security {
/**
* 防止SQL注入
*/
public static function cleanInput($data) {
return htmlspecialchars(strip_tags(trim($data)));
}
/**
* 生成JWT Token
*/
public static function generateJWT($user_id, $secret_key) {
$header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
$payload = json_encode([
'user_id' => $user_id,
'iat' => time(),
'exp' => time() + 3600 // 1小时有效
]);
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secret_key, true);
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
return $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
}
/**
* 验证JWT Token
*/
public static function verifyJWT($token, $secret_key) {
$tokenParts = explode('.', $token);
if (count($tokenParts) !== 3) return false;
$header = base64_decode($tokenParts[0]);
$payload = base64_decode($tokenParts[1]);
$signature = $tokenParts[2];
$expectedSignature = hash_hmac('sha256', $tokenParts[0] . "." . $tokenParts[1], $secret_key, true);
$expectedBase64 = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($expectedSignature));
if (!hash_equals($expectedBase64, $signature)) {
return false;
}
$payloadData = json_decode($payload, true);
if ($payloadData['exp'] < time()) {
return false; // Token过期
}
return $payloadData;
}
}
?>
使用说明
- 配置数据库:根据实际情况修改config.php中的数据库连接信息
- 配置短信服务:如果你有阿里云/腾讯云短信服务,在send_sms.php中配置
- 部署到服务器:将文件部署到支持PHP的服务器
- 测试流程:
- 打开login.html
- 输入手机号,点击获取验证码
- 查看数据库中sms_codes表的验证码(或查看控制台输出的调试验证码)
- 输入验证码登录
注意事项
- 生产环境:一定要禁用debug_code输出
- 邮件验证:可以考虑添加邮件验证码功能
- 验证码存储:生产环境建议使用Redis等缓存数据库
- Rate Limit:生产环境建议增加更完善的限流机制
- HTTPS:生产环境必须使用HTTPS加密传输
- 日志记录:建议记录所有登录操作日志
这个系统已经够用于学习或中小型项目,如果是在生产环境使用,建议进一步增强安全性。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播