php – 如何防止用户绕过必须遵循的步骤?

我有一个多表单向导,必须完成几个步骤,这个脚本的开发与普通脚本非常不同,我的脚本避免了用户填充的数据丢失,避免了丢失用户的步骤.

脚本的步骤保存在会话中,避免返回到开头,使它们始终保持在用户的当前步骤中.

但是,在必须遵循的步骤过程中存在漏洞问题.

如果恶意用户更改了URL的值,则采用以下方式:

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>

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>

saveTemp.PHP或者可以通过POST方法而不是GET方法接收步骤,从而避免更改URL(saveTemp.PHP?Step = 6)

<?PHP
session_start();

$step =  isset($_GET['step']) ?  $_GET['step'] : 1;

// 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);

解决方法:

完成表单处理后,将步骤放入会话变量中.当您处理下一次提交时,请检查$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);

相关文章

页面搜索关键词突出 // 页面搜索关键词突出 $(function () {...
jQuery实时显示日期、时间 html: &lt;span id=&quot...
jQuery 添加水印 &lt;script src=&quot;../../../.....
中文:Sys.WebForms.PageRequestManagerParserErrorExceptio...
1. 用Response.Write方法 代码如下: Response.Write(&q...
Jquery实现按钮点击遮罩加载,处理完后恢复 思路: 1.点击按...