前言
之前使用python写了一个口令生成器,点击查看,但只能在本地电脑上使用,外出了不方便查找口令,于是我将功能部署到服务器,但python负担有点大,于是想到了PHP。
体验
代码
体验的数据已加密,现开源的仅用户密码进行了加密,数据未加密,如下:
<?php
// MySQL 配置
$mysql_host = '127.0.0.1';
$mysql_db = 'random_char';
$mysql_user = 'random_char';
$mysql_password = '123456';
// 连接到 MySQL
$mysqli = new mysqli($mysql_host, $mysql_user, $mysql_password, $mysql_db);
if ($mysqli->connect_error) {
die(json_encode(["error" => "数据库连接失败:" . $mysqli->connect_error]));
}
// 生成随机字符串
function generateRandomString($length = 6, $type = 'numeric') {
// 定义字符集
$charSets = [
'numeric' => "0123456789",
'minuscule' => "abcdefghijklmnopqrstuvwxyz",
'majuscule' => "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
'symbols' => "()!@#$%^&*_-+=|{}[]:;'<>,.?",
];
// 组合多个字符集
$types = explode('+', $type);
// 合并字符集
$characters = '';
foreach ($types as $t) {
if (isset($charSets[$t])) {
$characters .= $charSets[$t];
} else {
// 如果类型不在预定义的字符集中,抛出异常
throw new InvalidArgumentException("无效的字符集类型: $t");
}
}
// 生成随机字符串
$randomString = '';
$charactersLength = strlen($characters);
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[random_int(0, $charactersLength - 1)];
}
return $randomString;
}
// 生成并保存字符串
function generateAndAppendString($mysqli, $username, $name, $length, $type) {
// 获取用户 ID
$stmt = $mysqli->prepare("SELECT id FROM users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->bind_result($userId);
$stmt->fetch();
$stmt->close();
// 查询已有的随机字符串
$existingRandomStrings = [];
$stmt = $mysqli->prepare("SELECT random_string FROM user_codes WHERE user_id = ? AND code_name = ?");
$stmt->bind_param('is', $userId, $name);
$stmt->execute();
$stmt->bind_result($randomString);
while ($stmt->fetch()) {
$existingRandomStrings[] = $randomString;
}
$stmt->close();
// 生成新的随机字符串
do {
$randomString = generateRandomString($length, $type);
} while (in_array($randomString, $existingRandomStrings));
// 插入代号和随机字符串
$stmt = $mysqli->prepare("INSERT INTO user_codes (user_id, code_name, random_string) VALUES (?, ?, ?)");
$stmt->bind_param('iss', $userId, $name, $randomString);
$stmt->execute();
$stmt->close();
return [
"代号" => $name,
"字符" => $randomString // 返回原始随机字符串
];
}
// 验证用户密码
function verifyPassword($mysqli, $username, $password) {
// 查询数据库获取用户存储的加密密码
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->bind_result($hashedPassword);
$stmt->fetch();
$stmt->close();
// 如果没有找到用户,返回 false
if (!$hashedPassword) {
return false;
}
// 使用 password_verify 函数检查密码是否匹配
return password_verify($password, $hashedPassword);
}
// 保存用户信息到 MySQL
function saveUserInfo($mysqli, $username, $password) {
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$stmt = $mysqli->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->bind_param('ss', $username, $hashedPassword);
$stmt->execute();
$stmt->close();
}
// 处理 HTTP 请求
header('Content-Type: application/json; charset=utf-8');
$method = $_SERVER['REQUEST_METHOD'];
$input = json_decode(file_get_contents('php://input'), true);
if ($method === 'POST' && isset($input['name'], $input['type'])) {
$username = isset($input['username']) ? trim($input['username']) : null;
$name = trim($input['name']);
$length = isset($input['length']) ? intval($input['length']) : 6;
$type = trim($input['type']);
if (empty($name) || $length <= 0) {
echo json_encode(["error" => "代号不能为空,且长度需大于 0。"]);
exit;
}
// 如果提供了用户名和密码,则验证并存储数据
if ($username) {
// 检查用户名是否已存在
$stmt = $mysqli->prepare("SELECT id FROM users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
// 如果用户存在,验证密码
if (!verifyPassword($mysqli, $username, $input['password'])) {
echo json_encode(["error" => "密码不正确。"]);
exit;
}
} else {
// 新用户,保存密码和信息
saveUserInfo($mysqli, $username, $input['password']);
}
// 生成随机字符串并保存
$response = generateAndAppendString($mysqli, $username, $name, $length, $type);
} else {
// 如果没有提供用户名和密码,只返回随机字符串
$response = [
"代号" => $name,
"字符" => generateRandomString($length, $type)
];
}
echo json_encode($response);
}
/*
Navicat Premium Data Transfer
Source Server : random_char
Source Server Type : MySQL
Source Server Version : 80403 (8.4.3)
Source Host : 127.0.0.1:3306
Source Schema : random_char
Target Server Type : MySQL
Target Server Version : 80403 (8.4.3)
File Encoding : 65001
Date: 14/12/2024 13:44:24
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user_codes
-- ----------------------------
DROP TABLE IF EXISTS `user_codes`;
CREATE TABLE `user_codes` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`code_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`random_string` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`timestamp` datetime NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
INDEX `user_id`(`user_id` ASC) USING BTREE,
CONSTRAINT `user_codes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 67 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`registration_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_used_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`username` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
评论区