本文目录导读:

我来为您介绍几种在 PHP 中实现图形锁的方案:
基于 JavaScript 的九宫格图形锁(推荐)
这种方案将图形锁的逻辑放在前端,PHP 只负责验证和处理结果。
HTML + JavaScript 部分
<!DOCTYPE html>
<html>
<head>
<style>
.lock-container {
width: 300px;
height: 300px;
margin: 50px auto;
position: relative;
background: #f0f0f0;
}
.lock-point {
width: 60px;
height: 60px;
border-radius: 50%;
background: #ccc;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background 0.3s;
}
.lock-point.active {
background: #4CAF50;
color: white;
}
.lock-point.selected {
background: #2196F3;
}
canvas {
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<div class="lock-container" id="lockContainer">
<canvas id="lockCanvas"></canvas>
<!-- 9个点 -->
<div class="lock-point" data-index="0" style="left: 20px; top: 20px;">1</div>
<div class="lock-point" data-index="1" style="left: 120px; top: 20px;">2</div>
<div class="lock-point" data-index="2" style="left: 220px; top: 20px;">3</div>
<div class="lock-point" data-index="3" style="left: 20px; top: 120px;">4</div>
<div class="lock-point" data-index="4" style="left: 120px; top: 120px;">5</div>
<div class="lock-point" data-index="5" style="left: 220px; top: 120px;">6</div>
<div class="lock-point" data-index="6" style="left: 20px; top: 220px;">7</div>
<div class="lock-point" data-index="7" style="left: 120px; top: 220px;">8</div>
<div class="lock-point" data-index="8" style="left: 220px; top: 220px;">9</div>
</div>
<input type="hidden" id="pattern" name="pattern">
<button onclick="submitPattern()">确认</button>
<button onclick="resetPattern()">重置</button>
<script>
class PatternLock {
constructor() {
this.container = document.getElementById('lockContainer');
this.canvas = document.getElementById('lockCanvas');
this.ctx = this.canvas.getContext('2d');
this.points = document.querySelectorAll('.lock-point');
this.selectedPoints = [];
this.isDrawing = false;
this.initCanvas();
this.bindEvents();
}
initCanvas() {
this.canvas.width = 300;
this.canvas.height = 300;
}
getPointPosition(point) {
return {
x: parseFloat(point.style.left) + 30,
y: parseFloat(point.style.top) + 30
};
}
bindEvents() {
this.points.forEach(point => {
point.addEventListener('mousedown', (e) => this.handlePointClick(e, point));
});
this.container.addEventListener('mousemove', (e) => this.handleMouseMove(e));
this.container.addEventListener('mouseup', () => this.handleMouseUp());
}
handlePointClick(e, point) {
e.preventDefault();
const index = parseInt(point.dataset.index);
if (!this.selectedPoints.includes(index)) {
this.selectedPoints.push(index);
point.classList.add('selected');
this.drawPattern();
}
this.isDrawing = true;
}
handleMouseMove(e) {
if (this.isDrawing) {
this.drawPattern();
}
}
handleMouseUp() {
this.isDrawing = false;
this.drawPattern();
}
drawPattern() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
if (this.selectedPoints.length > 0) {
this.ctx.beginPath();
this.ctx.strokeStyle = '#2196F3';
this.ctx.lineWidth = 3;
const startPos = this.getPointPosition(this.points[this.selectedPoints[0]]);
this.ctx.moveTo(startPos.x, startPos.y);
for (let i = 1; i < this.selectedPoints.length; i++) {
const pos = this.getPointPosition(this.points[this.selectedPoints[i]]);
this.ctx.lineTo(pos.x, pos.y);
}
this.ctx.stroke();
}
}
getPattern() {
return this.selectedPoints.join('-');
}
reset() {
this.selectedPoints = [];
this.points.forEach(point => point.classList.remove('selected'));
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.isDrawing = false;
}
}
const lock = new PatternLock();
function submitPattern() {
const pattern = lock.getPattern();
if (pattern.length < 5) { // 至少连接3个点
alert('至少需要连接3个点');
return;
}
// 发送到服务器
fetch('save_pattern.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ pattern: pattern })
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('图形锁设置成功!');
} else {
alert('设置失败:' + data.message);
}
});
}
function resetPattern() {
lock.reset();
}
</script>
</body>
</html>
PHP 后端处理
<?php
// save_pattern.php
session_start();
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'message' => '请求方法错误']);
exit;
}
$input = json_decode(file_get_contents('php://input'), true);
$pattern = isset($input['pattern']) ? $input['pattern'] : '';
// 验证图形锁的合法性
function validatePattern($pattern) {
if (empty($pattern)) {
return false;
}
$points = explode('-', $pattern);
// 至少需要3个点
if (count($points) < 3) {
return false;
}
// 检查是否有重复的点
if (count($points) !== count(array_unique($points))) {
return false;
}
// 检查每个点是否合法(0-8)
foreach ($points as $point) {
if (!is_numeric($point) || intval($point) < 0 || intval($point) > 8) {
return false;
}
}
return true;
}
// 将图形密码加密存储
function hashPattern($pattern) {
// 使用 password_hash 进行哈希处理
return password_hash($pattern, PASSWORD_DEFAULT);
}
if (validatePattern($pattern)) {
// 这里应该存储到数据库,这里用文件模拟存储
$user_id = $_SESSION['user_id'] ?? 1; // 假设用户ID为1
$hashed_pattern = hashPattern($pattern);
// 存储到文件或数据库
file_put_contents("pattern_{$user_id}.txt", $hashed_pattern);
$response = [
'success' => true,
'message' => '设置成功',
'pattern' => $pattern // 注意:生产环境不要返回明文密码
];
} else {
$response = [
'success' => false,
'message' => '无效的图形密码'
];
}
echo json_encode($response);
服务端验证模式
<?php
// verify_pattern.php
session_start();
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'message' => '请求方法错误']);
exit;
}
$input = json_decode(file_get_contents('php://input'), true);
$pattern = isset($input['pattern']) ? $input['pattern'] : '';
// 获取存储的图形密码
$user_id = $_SESSION['user_id'] ?? 1;
$stored_pattern_file = "pattern_{$user_id}.txt";
if (!file_exists($stored_pattern_file)) {
echo json_encode(['success' => false, 'message' => '未找到存储的密码']);
exit;
}
$stored_hash = file_get_contents($stored_pattern_file);
// 验证密码
if (password_verify($pattern, $stored_hash)) {
$_SESSION['unlocked'] = true;
echo json_encode(['success' => true, 'message' => '解锁成功']);
} else {
echo json_encode(['success' => false, 'message' => '密码错误']);
}
数据库存储版本
<?php
// DatabasePatternLock.php
class DatabasePatternLock {
private $db;
public function __construct($host, $username, $password, $dbname) {
$this->db = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
// 设置图形锁
public function savePattern($user_id, $pattern) {
// 验证图形
if (!$this->validatePattern($pattern)) {
return ['success' => false, 'message' => '无效的图形'];
}
$hashed_pattern = password_hash($pattern, PASSWORD_DEFAULT);
$sql = "INSERT INTO user_patterns (user_id, pattern_hash, created_at)
VALUES (:user_id, :pattern_hash, NOW())
ON DUPLICATE KEY UPDATE pattern_hash = :pattern_hash, updated_at = NOW()";
$stmt = $this->db->prepare($sql);
$stmt->execute([
':user_id' => $user_id,
':pattern_hash' => $hashed_pattern
]);
return ['success' => true];
}
// 验证图形锁
public function verifyPattern($user_id, $pattern) {
$sql = "SELECT pattern_hash FROM user_patterns WHERE user_id = :user_id";
$stmt = $this->db->prepare($sql);
$stmt->execute([':user_id' => $user_id]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result && password_verify($pattern, $result['pattern_hash'])) {
return true;
}
return false;
}
// 验证图案格式
private function validatePattern($pattern) {
$points = explode('-', $pattern);
if (count($points) < 3 || count($points) > 9) {
return false;
}
// 检查是否有重复
if (count($points) !== count(array_unique($points))) {
return false;
}
// 检查范围
foreach ($points as $point) {
if (!is_numeric($point) || intval($point) < 0 || intval($point) > 8) {
return false;
}
}
return true;
}
}
// 使用示例
$lock = new DatabasePatternLock('localhost', 'root', '', 'mydb');
$lock->savePattern($_SESSION['user_id'], '0-1-2-5-8');
$success = $lock->verifyPattern($_SESSION['user_id'], '0-1-2-5-8');
安全建议
- 密码加密:使用
password_hash()加密存储,不要明文存储 - 限制尝试次数:防止暴力破解
- 时间锁定:多次失败后锁定一段时间
- 使用 HTTPS:确保传输安全
- 输入验证:服务端也要验证输入的合法性
// 增加尝试次数限制的例子
function checkAttempts($user_id) {
$attempt_key = "failed_attempts_$user_id";
$attempts = $_SESSION[$attempt_key] ?? 0;
if ($attempts >= 5) {
// 锁定用户
$lock_time = $_SESSION['lock_time'] ?? 0;
if (time() - $lock_time < 300) { // 5分钟
return false;
} else {
// 重置
$_SESSION[$attempt_key] = 0;
unset($_SESSION['lock_time']);
return true;
}
}
return true;
}
这种实现方案既简单又安全,可以根据您的具体需求进行调整,建议在实际生产环境中使用数据库存储并添加更多安全措施。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播