
本文介绍如何通过 php 读取、定位并更新纯文本用户文件(格式为 username|phone|password)中特定用户的密码,避免直接操作数组导致数据丢失,并确保整行内容完整写回。
本文介绍如何通过 php 读取、定位并更新纯文本用户文件(格式为 username|phone|password)中特定用户的密码,避免直接操作数组导致数据丢失,并确保整行内容完整写回。
在基于文本文件的简易用户系统中,修改某位用户的密码需谨慎处理:不能仅替换密码字段后丢弃原始行结构,而应保持每行原始格式不变,仅更新目标字段值,并将全部行重新写入文件。以下是完整、安全的实现方案:
✅ 核心思路
- 读取整个
users.txt文件为字符串; - 按行分割为数组(保留原始换行结构);
- 遍历每一行,用
explode('|', $line)解析字段,校验用户名与手机号是否匹配; - 若匹配,基于原始字符串(非数组) 使用
str_replace()替换旧密码(带前导|以避免误替),确保分隔符和顺序不变; - 将处理后的所有行拼接为新内容,最后一次性写回文件。
✅ 完整可运行代码(change.php)
<?php if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: index.php?status=invalidRequest');
exit;
}
$username = trim($_POST['username'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$new_password = 'newpassword'; // 实际项目中应从 POST 获取并加密(如 password_hash())
// 验证输入非空
if (empty($username) || empty($phone)) {
header('Location: index.php?status=missingFields');
exit;
}
$filename = 'users.txt';
if (!file_exists($filename)) {
header('Location: index.php?status=fileNotFound');
exit;
}
$lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$lines) {
header('Location: index.php?status=emptyFile');
exit;
}
$new_content = '';
$user_found = false;
foreach ($lines as $line) {
$parts = explode('|', $line, 3); // 限制分割为最多3段,防止密码含'|'被误切
if (count($parts) !== 3) continue; // 跳过格式异常行
[$stored_username, $stored_phone, $stored_password] = $parts;
if ($stored_username === $username && $stored_phone === $phone) {
// 精确替换:用 '|新密码' 替换 '|旧密码',避免跨字段污染
$line = str_replace('|' . $stored_password, '|' . $new_password, $line);
$user_found = true;
}
$new_content .= $line . PHP_EOL;
}
if (!$user_found) {
header('Location: index.php?status=userNotFound');
exit;
}
// 原子写入:先写临时文件,再重命名,避免写入中断导致数据损坏
$temp_file = $filename . '.tmp';
if (file_put_contents($temp_file, $new_content) === false) {
header('Location: index.php?status=writeFailed');
exit;
}
if (!rename($temp_file, $filename)) {
unlink($temp_file);
header('Location: index.php?status=writeFailed');
exit;
}
header('Location: index.php?status=passwordChanged');
exit;
?>
⚠️ 关键注意事项
-
安全性提醒:生产环境绝不可明文存储密码!务必使用
password_hash($new_password, PASSWORD_ARGON2ID)加密,并用password_verify()校验——本例仅演示文本替换逻辑。 -
防误替换:
str_replace('|'.$old, '|'.$new, $line)中的|前缀确保只替换密码字段,而非用户名或手机号中偶然出现的相同字符串。 -
鲁棒性增强:使用
file()+FILE_IGNORE_NEW_LINES代替file_get_contents()+explode(),更可靠处理不同换行符(\n,\r\n);explode(..., 3)防止密码含|导致解析错位。 -
原子写入:通过临时文件+
rename()保证写入过程不中断原有数据,避免并发写入时文件损坏。
✅ 后续建议
- 在表单中增加新密码输入框及确认校验;
- 添加错误日志记录(如
error_log("User {$username} password updated")); - 对敏感操作(如密码修改)增加 CSRF Token 防护。
此方案兼顾简洁性与健壮性,适用于教学场景下的文件型用户管理,同时为后续升级至数据库奠定清晰逻辑基础。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











