我有一个多表单向导,需要完成多个步骤,该脚本可防止用户填写的数据丢失并防止用户步骤丢失。
脚本步骤保存在避免回到开头的会话中,始终将它们保留在用户的当前步骤中。
但是我在需要遵循的步骤的过程中存在漏洞问题。
如果恶意用户更改 URL 值,如下所示:
localhost/wizard/saveTemp.php?step=6
该恶意用户可以随意跳过这些步骤,从而绕过系统。
例子:
用户在步骤1
中,但我修改URL
并自动跳转到步骤6
。
注意:第二种绕过系统的方法是通过添加或代码来修改&
HTML
链接的代码。示例:就像修改URL一样自动跳转到 step 。atrás
continuar
multi form wizard
consola
atributos
javascript
<a href="#" class="next" onclick="show_step('6')>Continuar</a>
PHP
6
然后,
如何通过使用添加强化控件来防止系统被嘲笑
PHP
,其中用户不能从一步1
到一步3
或一步6
,但必须继续步骤的顺序1, 2, 3, 4, 5, 6
等等。如何
PHP
使用 Javascript 的现有验证集验证向导表单的字段?
我的代码
脚本向导
<?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>
HTML结构
<form id="form">
<div id="step1" class="step">
<h1>Step 1</h1>
<a href="#next" class="next">next</a>
</div>
<div id="step2" class="step">
<h1>Step 2</h1>
<a href="#back" class="back">back</a>
<a href="#next" class="next">next</a>
</div>
<div id="step3" class="step">
<h1>Step 3</h1>
<a href="#back" class="back">back</a>
<a href="#next" class="next">next</a>
</div>
<div id="step4" class="step">
<h1>Step 3</h1>
<a href="#back" class="back">back</a>
<a href="#next" class="next">next</a>
</div>
<div id="step5" class="step">
<h1>Step 3</h1>
<a href="#back" class="back">back</a>
<a href="#next" class="next">next</a>
</div>
<div id="step6" class="step">
<h1>Step 4</h1>
<a href="#back" class="back">back</a>
</div>
</form>
保存临时文件
注意:已收到评论说程序错误,您现在无法传递数据
POST
并GET
实际使用它,?
在这些评论之前对我来说是未知的,此程序是由Xerif 的回应采取的
<?php
session_start();
$step = isset($_GET['step']) ? $_GET['step'] : 1;
// We save the form data in a session variable
$_SESSION['datos_form'] = $_POST;
// we also add the step to the array, you can not use this name (__step__) as name in the form
$datosForm = (isset($_SESSION['datos_form']) && is_array($_SESSION['datos_form'])) ? $_SESSION['datos_form'] :array();
$sStep = isset($datosForm['__step__']) ? $datosForm['__step__'] : 1;
$step = isset($step) ? $step : $sStep;
$radio = isset($datosForm['radio']) ? $datosForm['radio'] : 1;
$_SESSION['datos_form']['__step__'] = $step;
header('Content-Type: application/json');
$json = array(
'radio' => $radio,
'step' => $step
);
echo json_encode($json);
过程:
因此,由于我们已经定义了步骤,在
$step
a 中的变量中sesión
,当下一步/发送正在发送/处理时,检查它$step
是否是下一步。或者你可能对加密方法发送的值感兴趣
GET
,在以下来源中你可以分析。其他感兴趣的话题
使用它创建一个与脚本
PHP
工作方式相同的向导实际上不可能执行相同的机制,并且这样做时,数据必须发送到同一页面,我不认为该程序是想要的。jQuery
假设用户在浏览器中禁用了使用
javascript
,所有的步骤会同时显示,就好像它是一个单一的,form
虽然实际上是这样,只是在使用脚本jQuery
时它们被分成了部分。然后使用
PHP
它验证表单将以正常方式进行,即在使用空数据执行发送时,为每个input
空字段执行错误。步骤无关紧要,步骤的顺序也无关紧要,客户端发生的任何事情也无关紧要。浏览器/浏览器中发生的事情是不可信的。如果您打算作为 Web 开发人员工作,您必须了解Web 客户端中发生的事情是不可信的。因此,解决这种“不信任”问题的唯一方法是: 在服务器上接收到所有数据时重新验证所有数据。换句话说,在完成向导之后,在接受操作并将数据保存到数据库之前,同时验证所有数据(在 6 个步骤中恢复的数据)。
本质上,这是客户端-服务器架构的一个特性。
无论您使用的是 PHP、C# 还是 Node.js。
客户端验证是为了使界面对用户“友好”,并且应该以用户为中心。它们对于所谓的“用户体验”至关重要,与恶意用户没有太大关系,最终它们可以在不使用 Web 界面的情况下攻击您的系统,使用类似 PostMan 的工具直接调用 PHP 脚本。
相反,服务器端验证是检查数据是否完整且有效。这包括您作为架构师认为必要的所有验证。例如,是否验证“电子邮件”字段的格式。
我再说一遍,它们是具有不同目的的不同验证,它们也是不同的应用程序。这里没有代码重用的基础。
保存它在会话中执行的步骤。并在进行下一步时,验证它是否正确。请求该值并通过 ajax 更新它。
尽管如果您认为这对服务器来说将是很多工作。您可以创建具有单个常量元素的数组。该元素将保存您所在的步骤。更改“步骤”会删除先前的常量变量并将其替换为当前步骤。
在伪代码中它将是:
我希望它被理解。这样你就不需要 ajax,你仍然可以使用 GET 或 POST。
您可以通过 POST 传递该步骤的值,或者使用您的框架的路由器强制请求仅通过 POST 的该 url,否则重定向到步骤 1。