基于Session实现file_get_contents自定义文件读取路径的问题
问题梳理
你当前的代码存在几个核心逻辑问题,导致无法实现用户输入文件名后加载对应JSON的需求:
- input.php中表单提交按钮的
name属性是apply,但你写的接收条件是isset($_POST['submit']),参数匹配不上,提交后逻辑不会触发 - index.php的判断条件逻辑错误:只要调用了
session_start(),session_id() !== ''就永远成立,所以你写的加载用户指定文件的else分支永远不会执行 - 没有对用户输入的文件名做合法性校验,直接拼接路径会存在目录遍历安全漏洞,用户输入
../xxx这类内容会读取到非指定目录的敏感文件 - 拼接文件名前没有判断文件是否真实存在,容易触发文件不存在的PHP报错
修复后代码
input.php
<?php session_start(); include ("connection.php"); include ("functions.php"); $user_data = check_login($con); ?> <!DOCTYPE html> <html> <head> <title>Update News File</title> </head> <body> <form action='../test/index.php' method='post'> <label for="fname">File name:</label> <input type="text" name="fname" required><br><br> <input type="submit" id="buttonS" name="apply" value="Apply"> </form> </body> </html>
index.php
<?php session_start(); $local_dir = 'C:\xampp\htdocs\jsonFile'; $default_file = 'Ass2News.json'; function checkDir($dir) { return array_values(array_diff(scandir($dir) , array( '.', '..' ))); } // 读取目录下所有合法文件做白名单 $allow_files = checkDir($local_dir); // 处理用户提交的文件名 if (isset($_POST['fname'])) { $input_name = trim($_POST['fname']); $target_file = $input_name . '.json'; // 校验文件是否在白名单内,杜绝路径遍历风险 if (in_array($target_file, $allow_files)) { $_SESSION['nameF'] = $input_name; } else { // 非法文件名则回退到默认文件 $_SESSION['nameF'] = pathinfo($default_file, PATHINFO_FILENAME); } } // 确定最终加载的文件 if (!isset($_SESSION['nameF'])) { $load_path = '../jsonFIle/' . $default_file; } else { $load_path = '../jsonFIle/' . $_SESSION['nameF'] . '.json'; } // 解析JSON $jsonData = file_get_contents($load_path); $json = json_decode($jsonData, true); ?>
开发注意点
- 用户输入的内容永远不能直接用来拼接文件路径,必须做白名单校验,上面的代码用目录内实际存在的文件做匹配是最安全的处理方式
- 上线前可以开启PHP错误提示,方便快速定位逻辑问题
- 当前代码已经自动给用户输入的内容补
.json后缀,用户只需要输入文件名即可,比如要加载test.json,输入test就可以正常识别
内容的提问来源于stack exchange,提问作者Darke
相关产品推荐
相关产品推荐

