Php 如何防止用户绕过必须遵循的步骤过程?
我有一个多表单向导,有几个必须完成的步骤,这个脚本的开发与普通脚本非常不同,我的脚本避免了用户填写的数据丢失,也避免了丢失用户的步骤 脚本的步骤保存在一个会话中,该会话避免返回到开头,始终保持在用户的当前步骤中 但我在采取步骤的过程中遇到了一个漏洞问题 如果恶意用户以以下方式更改URL的值:Php 如何防止用户绕过必须遵循的步骤过程?,php,jquery,Php,Jquery,我有一个多表单向导,有几个必须完成的步骤,这个脚本的开发与普通脚本非常不同,我的脚本避免了用户填写的数据丢失,也避免了丢失用户的步骤 脚本的步骤保存在一个会话中,该会话避免返回到开头,始终保持在用户的当前步骤中 但我在采取步骤的过程中遇到了一个漏洞问题 如果恶意用户以以下方式更改URL的值: localhost/wizard/saveTemp.php?step=6 该用户可以根据您的意愿跳过这些步骤 示例用户在步骤1中,但我修改了url并自动跳转到步骤6 因此,我如何通过使用PHP添加一个增强
localhost/wizard/saveTemp.php?step=6
该用户可以根据您的意愿跳过这些步骤
示例用户在步骤1中,但我修改了url并自动跳转到步骤6
因此,我如何通过使用PHP添加一个增强的控件来防止他们戏弄系统,用户不能从步骤1跳到步骤3或步骤6,而是必须继续执行步骤1、2、3、4、5、6等的顺序
我的脚本向导
<?php
session_start();
if (isset($_GET['p'])) {
session_destroy();
session_start();
}
?>
<script>
var currentStep = <?php echo $step ?>; // Variable indicating the current step, data selected with PHP sessions
var radio = <?php echo $radio ?>; //Value of the radius selected
function show_step(step) {
var data = $("#form").serialize();
var url = 'saveTemp.php?step=' + step;
var valid = true;
// [OPTIONAL] Validate only if you are going forward
if (currentStep < step) {
// We search all the fields within the current step.
$('#step' + currentStep).find('input,textarea,select').each((idx, el) => {
let $field = $(el);
let $fieldCont = $field.closest('.form-group');
// If the field is a checkbox or a radio and an option was not selected
if (($field.prop('type') == 'checkbox' || $field.prop('type') == 'radio') &&
!$fieldCont.find('input[name="'+$field.prop('name')+'"]:checked').length) {
$fieldCont.addClass('error');
valid = false;
}
// If the field is NOT a checkbox or a radio and is empty
else if ($field.prop('type') != 'checkbox' && $field.prop('type') != 'radio' &&
!$field.val()) {
$fieldCont.addClass('error');
valid = false;
} else {
$fieldCont.removeClass('error');
}
});
}
// If at least one field was not completed
if (!valid) {
return;
}
//
$.ajax({
type: "POST",
url: url,
data: data
}).done(function(resp){
$('#radio').val(resp.radio);
if (step === 2) {
var radio = parseInt(resp.radio);
switch(radio) {
case 1:
urlform = './app/themes/pay_paypal.php'
break;
case 2:
urlform = './app/themes/pay_paypal2.php'
break;
case 3:
urlform = './app/themes/pay_paypal3.php'
break;
default:
urlform = './app/themes/pay_paypal4.php'
break;
}
$('#divPay').load(urlform,function(responseTxt, statusTxt, xhr){
if(statusTxt === "success") {
$('#step' + currentStep).css("display", "none");
$('#step' + step).fadeIn("slow");
currentStep = step;
}
if(statusTxt === "error") {
//
}
});
} else {
$('#step' + currentStep).css("display", "none");
$('#step' + step).fadeIn("slow");
currentStep = step;
}
});
};
$(function() {
show_step(currentStep);
$('a.next').click(e => {
e.preventDefault();
show_step(currentStep + 1);
});
$('a.back').click(e => {
e.preventDefault();
show_step(currentStep - 1);
});
});
</script>
完成表单处理后,将步骤放入会话变量中。处理下一次提交时,请检查
$step
是否为下一步
$last_step = isset($_SESSION['step']) ? $_SESSION['step'] : 0;
if ($step > $last_step + 1) {
die("You can't jump directly from step $last_step to $step");
}
在脚本结束时,验证所有信息后,将步骤保存在会话变量中:
$_SESSION['step'] = $step;
完整代码:
<?php
session_start();
$step = isset($_GET['step']) ? $_GET['step'] : 1;
$last_step = isset($_SESSION['data_form']['__step__']) ? $_SESSION['data_form']['__step__'] : 0;
if ($step > $last_step + 1) {
die(json_encode(array('error' => 'Invalid step')));
}
// We save the form data in a session variable
$_SESSION['data_form'] = $_POST;
// we also add the step to the array, you can not use this name (__step__) as name in the form
$dataForm = (isset($_SESSION['data_form']) && is_array($_SESSION['data_form'])) ? $_SESSION['data_form'] :array();
$sStep = isset($dataForm['__step__']) ? $dataForm['__step__'] : 1;
$step = isset($step) ? $step : $sStep;
$radio = isset($dataForm['radio']) ? $dataForm['radio'] : 1;
$_SESSION['data_form']['__step__'] = $step;
header('Content-Type: application/json');
$json = array(
'radio' => $radio,
'step' => $step
);
echo json_encode($json);
我建议你不要这样做
我的意思是:我发现你也会验证用户输入,如果当前输入没有正确填写,就不允许用户进入下一步
我还发现,至少要在服务器端验证输入
默认情况下,没有任何子表单是有效的(没有任何用户输入),或者,如果是这样,您可以简单地添加一个隐藏的输入,并在某些事件(例如加载表单步骤)上自动填充它;您只需在每次请求任何步骤时重新验证整个表单(直到所需步骤)
例如,如果客户端请求第6步,但第5步未经验证,只需将http重定向头发送到第5步,或者发送一些最小的html错误,建议执行此操作,并提供手动执行此操作的链接。使用POST方法没有帮助。用户可以使用开发人员工具更改带有步骤号的隐藏输入。@Barmar哇,我没想到会这样,谢谢您的澄清。Friend不起作用,请向我显示错误消息。会话变量设置正确吗?您是在设置了$step=isset($\u GET['step'])
的代码之后执行此操作的吗?并且您执行了$\u会话['step']=$step代码>在脚本的末尾?问题是“必须继续执行步骤1、2、3、4、5、6等的顺序”。没有任何关于向后执行的内容。无论如何,如果您希望减少限制,您应该可以轻松修改上述代码中的逻辑。你真的需要我为你写整件事吗?你不是一个程序员,难道你不能从我写的东西中推断出来吗?
$_SESSION['step'] = $step;
<?php
session_start();
$step = isset($_GET['step']) ? $_GET['step'] : 1;
$last_step = isset($_SESSION['data_form']['__step__']) ? $_SESSION['data_form']['__step__'] : 0;
if ($step > $last_step + 1) {
die(json_encode(array('error' => 'Invalid step')));
}
// We save the form data in a session variable
$_SESSION['data_form'] = $_POST;
// we also add the step to the array, you can not use this name (__step__) as name in the form
$dataForm = (isset($_SESSION['data_form']) && is_array($_SESSION['data_form'])) ? $_SESSION['data_form'] :array();
$sStep = isset($dataForm['__step__']) ? $dataForm['__step__'] : 1;
$step = isset($step) ? $step : $sStep;
$radio = isset($dataForm['radio']) ? $dataForm['radio'] : 1;
$_SESSION['data_form']['__step__'] = $step;
header('Content-Type: application/json');
$json = array(
'radio' => $radio,
'step' => $step
);
echo json_encode($json);