XMLHttpRequests, пользовательские заголовки данных POST и проверка - PullRequest
0 голосов
/ 02 января 2012

Прошу отзыв.Я пытался найти хороший метод проверки клиентских отправленных POST-данных и наткнулся на заголовок Content-MD5.

Вот мое решение, первая часть использует функцию jQuery .ajax () вФорма простого в использовании плагина.Для этого требуются библиотеки шифрования pidder для функций md5 () и base64_encode (), необходимые для заголовка Content-MD5.

<script src="javascripts/pidcrypt.js"></script>
<script src="javascripts/pidcrypt_util.js"></script>
<script src="javascripts/md5.js"></script>
<script>
(function($){
 $.fn.AJAX = function(method) {
  var defaults = {
   formID: $(this),
   appID: 'jQuery.AJAX',
   cache: true,
   context: $(this),
   type: 'json',
   callback: function(){},
   errCallback: function(){}
  };
  var methods = {
   init: function(o){
    var opts = $.extend({}, defaults, o);
    $('#'+opts.formID.attr('id')).on('submit', function(e){
     e.preventDefault();
     $.ajax({
      form: opts.formID.attr('id'),
      url: opts.formID.attr('action'),
      type: opts.formID.attr('method'),
      data: opts.formID.serialize(),
      context: opts.context,
      cache: opts.cache,
      crossDomain: (opts.type==='jsonp') ? true : false,
      dataType: opts.type,
      beforeSend: function(xhr) {
       xhr.setRequestHeader('X-Alt-Referer', opts.appID);
       if (opt.formID.serialize()){
        xhr.setRequestHeader('X-Alt-Referer', pidCryptUtil.encodeBase64(pidCrypt.MD5($(this).serialize())));
       } else {
        xhr.setRequestHeader('X-Alt-Referer', pidCryptUtil.encodeBase64(pidCrypt.MD5(appID)));
       }
      },
      success: function(x){
       ((opts.callback)&&($.isFunction(opts.callback))) ?
         opts.callback.call(x) : console.log(x);
      },
      error: function(xhr, status, error){
       ((opts.errCallback)&&($.isFunction(opts.errCallback))) ?
         opts.errCallback.call(xhr, status, error) : console.log(xhr+status+error);
      }
     });
     return true;
    });
   }
  };
  if (methods[method]){
   return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  } else if ((typeof method==='object')||(!method)){
   return methods.init.apply(this, arguments);
  } else {
   console.log('Method '+method+' does not exist');
  }
 };
})(jQuery);}

Чтобы использовать плагин, просто создайте HTMLформа вот так ...

<form id="test" name="test" method="post" action="proxy.php">
 <label for="name">Name: <span class="required">*</span></label>
  <input type="text" id="name" name="name" value="" placeholder="John Doe" required="required" />
 <label for="email">Email Address: <span class="required">*</span></label>
  <input type="email" id="email" name="email" value="" placeholder="johndoe@example.com" required="required" />
 <label for="email">Confirm Email: <span class="required">*</span></label>
  <input type="email" id="email" name="email" value="" placeholder="johndoe@example.com" required="required" />
</form>

Теперь привязать плагин к форме вот так ...

$('#test').AJAX();

На этом этапе работающий клиентский метод отправки данных POST вскрипт proxy.php на месте.Единственное существенное отличие здесь состоит в том, что вместо простой отправки данных формы форм некоторые пользовательские заголовки отправляются вместе с данными формы XMLHttpRequest.

Теперь на сервере выполняется несколько простых проверок.Сначала проверьте, чтобы запрос был XMLHttpRequest, затем проверьте, чтобы убедиться, что X-Alt-Referer совпадает, затем он проверит, чтобы убедиться, что данные поста соответствуют тем же совпадениям хеш-данных поста (сериализованным) перед обработкой.Технически это работает очень похоже на контрольную сумму.

<?php
/* set the custom applicaiton string */
$appID = 'jQuery.AJAX'; // the plug-in URL https://github.com/jas-/jQuery.AJAX

/* verify an XMLHttpRequest was made */
if (strcmp($_SERVER['HTTP_X_REQUESTED_WITH'], 'XMLHttpRequest')!==0){
 exit('An XMLHttpRequest was not made');
}

/* verify associated X-ALT-Header value */
if (strcmp($_SERVER['HTTP_X_ALT_REFERER'], $appID)!==0){
 exit('The X-Alt-Referer information recieved is invalid');
}

/* verify associated Content-MD5 header value */
if (strcmp(base64_decode($_SERVER['HTTP_CONTENT_MD5']), md5(serialize($_POST)))!==0){
 exit('The Content-MD5 value is incorrect');
}
?>

У кого-нибудь есть причины НЕ использовать этот тип проверки данных POST?Заранее спасибо.

1 Ответ

0 голосов
/ 02 января 2012

От чего вы пытаетесь защититься?Заголовок Content-MD5 - достойное решение для защиты от ошибок передачи, которые не обнаруживаются контрольной суммой TCP, что происходит чаще, чем большинство людей осознают.Против злоумышленника, активно изменяющего данные, это совершенно бесполезно, поскольку злоумышленник может просто пересчитать заголовок.

Единственная причина не использовать этот заголовок - это производительность, поскольку на стороне клиента и на стороне сервера есть издержки (подумайтемобильные клиенты например).Вы должны взвесить стоимость с (небольшой) защитой, которую он вам предлагает.

Я нашел эту запись в блоге полезной по этому вопросу.

...