Всем добра! Парни, есть pjax. Как обновить токен после отправки формы? На странице несколько форм срабатывает только одна любая форма, потом все недоступны. Обновил страницу и все по кругу. PHP: <input type="hidden" name="_tocken" value="fyvrt568b7456765">
имхо токен должен меняться только после перезагрузки страницы, если отсылаешь ajax то вроде тот же должен оставаться может дело в корректности написания имени? не Код (Text): name="_token" ?
Отдельно. Свой мини MVC. --- Добавлено --- Разницы нет. Хоть qwerty, но потом qwerty и чекаем. Ну pjax и так обновляет страницу и токен в форме меняется. Пока столкнулся с такой проблемой... Первый раз форма отправляется нормально, второй раз получаю abord Код (Javascript): $('html').on('pjax:error', function(event, xhr, textStatus, errorThrown, options) { options.success(xhr.responseText, textStatus, xhr); console.log(xhr.responseText); console.log(textStatus); // <- тут abord console.log(xhr); return false; });
Это в контроллере. Если false, то выводим ошибку. PHP: if (NoCSRF::check( '_token', $_POST, false, 60, false ) == false) { $errors = $langerrors['s']; } Спойлер: это NoCSRF PHP: <?php /** * NoCSRF, an anti CSRF token generation/checking class. * * Copyright (c) 2011 Thibaut Despoulain <http://bkcore.com/blog/code/nocsrf-php-class.html> * Licensed under the MIT license <http://www.opensource.org/licenses/mit-license.php> * * @author Thibaut Despoulain <http://bkcore.com> * @version 1.0 */ class NoCSRF { protected static $doOriginCheck = false; /** * Check CSRF tokens match between session and $origin. * Make sure you generated a token in the form before checking it. * * @param String $key The session and $origin key where to find the token. * @param Mixed $origin The object/associative array to retreive the token data from (usually $_POST). * @param Boolean $throwException (Facultative) TRUE to throw exception on check fail, FALSE or default to return false. * @param Integer $timespan (Facultative) Makes the token expire after $timespan seconds. (null = never) * @param Boolean $multiple (Facultative) Makes the token reusable and not one-time. (Useful for ajax-heavy requests). * * @return Boolean Returns FALSE if a CSRF attack is detected, TRUE otherwise. */ public static function check( $key, $origin, $throwException=false, $timespan=null, $multiple=false ) { if ( !isset( $_SESSION[ 'csrf_' . $key ] ) ) if($throwException) throw new Exception( 'Missing CSRF session token.' ); else return false; if ( !isset( $origin[ $key ] ) ) if($throwException) throw new Exception( 'Missing CSRF form token.' ); else return false; // Get valid token from session $hash = $_SESSION[ 'csrf_' . $key ]; // Free up session token for one-time CSRF token usage. if(!$multiple) $_SESSION[ 'csrf_' . $key ] = null; // Origin checks if( self::$doOriginCheck && sha1( $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) != substr( base64_decode( $hash ), 10, 40 ) ) { if($throwException) throw new Exception( 'Form origin does not match token origin.' ); else return false; } // Check if session token matches form token if ( $origin[ $key ] != $hash ) if($throwException) #throw new Exception( 'Invalid CSRF token. <br>'.$origin[ $key ].'<br>='.$hash ); throw new Exception( 'Invalid CSRF token.'); else return false; // Check for token expiration if ( $timespan != null && is_int( $timespan ) && intval( substr( base64_decode( $hash ), 0, 10 ) ) + $timespan < time() ) if($throwException) throw new Exception( 'CSRF token has expired.' ); else return false; return true; } /** * Adds extra useragent and remote_addr checks to CSRF protections. */ public static function enableOriginCheck() { self::$doOriginCheck = true; } /** * CSRF token generation method. After generating the token, put it inside a hidden form field named $key. * * @param String $key The session key where the token will be stored. (Will also be the name of the hidden field name) * @return String The generated, base64 encoded token. */ public static function generate( $key ) { $extra = self::$doOriginCheck ? sha1( $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) : ''; // token generation (basically base64_encode any random complex string, time() is used for token expiration) $token = base64_encode( time() . $extra . self::randomString( 32 ) ); // store the one-time token in session $_SESSION[ 'csrf_' . $key ] = $token; return $token; } /** * Generates a random string of given $length. * * @param Integer $length The string length. * @return String The randomly generated string. */ protected static function randomString( $length ) { $seed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijqlmnopqrtsuvwxyz0123456789'; $max = strlen( $seed ) - 1; $string = ''; for ( $i = 0; $i < $length; ++$i ) $string .= $seed{intval( mt_rand( 0.0, $max ) )}; return $string; } } ?> --- Добавлено --- UPDATE: генерится так PHP: NoCSRF::generate( '_token' )
ну а сама check что делает посмотреть? --- Добавлено --- ну дык видно ж даже по описанию а у тебя false, поставь true
Пробовал уже, не помогло. Сейчас еще раз проверил - ни как. Тупо обновляется страница и все (при отправке еще одной формы).
Обычная форма: Код (Text): <form action="/shop" method="POST" class="shopcard" data-pjax> <input type="hidden" name="_token_shop_<?=$plan['id']; ?>" value="<?=NoCSRF::generate( '_token_shop_'.$plan['id'] ); ?>"> <input type="hidden" name="buy" value="1"> <input type="hidden" name="plan" value="<?=$plan['id']; ?>"> <div class="shopcard__btn"> <button type="submit" name="buy" class="btn btn-primary">Купить</button> </div> </form> JS код Код (Javascript): $('html').on('submit', 'form[data-pjax]', function(event) { $.pjax.submit(event, '#pjax-container', {fragment: '#pjax-container', type: 'post', scrollTo: 0, timeout: 10000}); //asnyc: false, push: true, enablePushState: true //console.log("gooo"+event); }); Страница обернута <div id="pjax-container"> --- Добавлено --- UPDATE: Токен у каждой формы свой. Мб в этом трабл? Типо _token_shop_1 _token_shop_2 _token_shop_3 и т.д.
Нет, тоже разные. PHP: if (NoCSRF::check( '_token_shop_'.$plan['id'], $_POST, false, 60, true ) == false) { $errors = $langerrors['s']; } --- Добавлено --- Что делать? Куда копать? Почему abort? Есть еще вот такая шляпа: Код (Javascript): $(document).on('pjax:end', function () { contentLoaded(); $('html, body').animate({ scrollTop: $(".section").offset().top }, 0); }); Вот contentLoaded() Спойлер Код (Javascript): "use strict";function contentLoaded(){document.getElementById("preloader").classList.add("loaded");var t=document.getElementsByClassName("js-youtube"),e=t.length;function a(){var t=document.createElement("iframe"),e="https://www.youtube.com/embed/"+this.id+"?autoplay=1&autohide=1";this.getAttribute("data-params")&&(e+="&"+this.getAttribute("data-params")),t.setAttribute("src",e),t.setAttribute("frameborder","0"),t.setAttribute("allowfullscreen","1"),t.setAttribute("width","100%"),t.setAttribute("height","100%"),this.innerHTML="",this.appendChild(t),this.removeEventListener("click",a)}for(var s=0;s<e;s++){t[s].getAttribute("data-background")&&(t[s].style.backgroundImage="url(https://i.ytimg.com/vi/"+t[s].id+"/sddefault.jpg)");var i=document.createElement("div");i.setAttribute("class","play"),t[s].appendChild(i),t[s].addEventListener("click",a)}!function(){var t=document.getElementsByClassName("section"),e=document.getElementById("block-content");if(t.length){var a=t[0],s=parseInt(a.clientHeight),i=Math.floor((s-100)/418);i<1?e.setAttribute("class","x1"):15<i?e.setAttribute("class","x15"):e.setAttribute("class","x"+i)}}()}document.addEventListener("DOMContentLoaded",contentLoaded); //# sourceMappingURL=common.js.map
Затрудняюсь ответить. В JS не особо силен... Пытался по строкам разложить и понять не смог --- Добавлено --- Убрал contentLoaded() и все что с этим связано. Без изменений. Получается так: первый раз отправляем любую форму - все ок. Второй раз эту же или любую другую, то уже все не отправляется тупо обновление страницы и все. Типо не видит форму? Токен меняется.
Обновлять вместе с формой когда данные отослал или отдельно. Вот отослал ты запрос, если успешно выполнился он то с бакенда формируй новый и отбавай его в success и затем через js изменяй в инпуте.