Heim  >  Artikel  >  Backend-Entwicklung  >  javascript - 手机表单提交页面,如果在网络慢的情况下,form表单会提交两次

javascript - 手机表单提交页面,如果在网络慢的情况下,form表单会提交两次

WBOY
WBOYOriginal
2016-10-22 00:14:241285Durchsuche

手机网站提交页面,网络好的时候正常,网络慢的时候手机页面会一直在加载状态,但是Fiddler抓取却有两次相同内容的提交,如何避免这种情况发生?

回复内容:

手机网站提交页面,网络好的时候正常,网络慢的时候手机页面会一直在加载状态,但是Fiddler抓取却有两次相同内容的提交,如何避免这种情况发生?

我的做法是在服务端生成一个token,提交的时候验证token,这是第一道验证,第二道验证为在表单提交时
将提交按钮设置为disabled,一般做个第二种验证就可以了

<code>// 提交表单数据到后台处理
$.ajax({
    type: "post",
    data: studentInfo,
    contentType: "application/json",
    url: "/Home/Submit",
    beforeSend: function () {
        // 禁用按钮防止重复提交
        $("#submit").attr({ disabled: "disabled" });
    },
    success: function (data) {
        if (data == "Success") {
            //清空输入框
            clearBox();
        }
    },
    complete: function () {
        $("#submit").removeAttr("disabled");
    },
    error: function (data) {
        console.info("error: " + data.responseText);
    }
});</code>

Csrf 验证类

<code><?php // +----------------------------------------------------------------------
// | CSRF安全验证类 @pushaowei
// +----------------------------------------------------------------------
// | [Usage]
// |    // 后端
// |    use library\Base\NoCSRF;
// |    session_start();   
// |    if ($this->getRequest()->isPost()) {
// |            
// |        try {
// |            ##验证TOKEN  
// |            NoCSRF::check( 'csrf_token', $_POST, true, 60*10, false ); //60*10为10分钟(null为不验证时间)
// |            $result = 'CSRF check passed. Form parsed.';
// |            //$this->getRequest()->getPost('field');
// |            echo $result;       
// |        } catch ( Exception $e ) {
// |            echo $e->getMessage() . ' Form ignored.'; 
// |        }      
// |    } else {   
// |        #生成TOKEN  
// |        $token = NoCSRF::generate( 'csrf_token' );
// |        $this->getView()->assign('token', $token);
// |        $this->getView()->display('页面');
// |    }
// |    // 前端
// |    <input type="hidden" name="csrf_token" value="{$token}">
// +----------------------------------------------------------------------

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 )
    {
        $session = Session::getInstance();

        if ( !$session->has( '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->get('csrf_' . $key);
        
        // Free up session token for one-time CSRF token usage.
        if(!$multiple)
            $session->forget('csrf_' . $key);

        // 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.' );
            else
                return false;

        // Check for token expiration
        if ( $timespan != null && is_int( $timespan ) && intval( substr( base64_decode( $hash ), 0, 10 ) ) + $timespan put('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 </code>

肯定是点击一次,提交一次,不可能因为网络慢就出现你点一次提交两次的情况——事件的触发,怎么可能像无根之水一样的?如果真有这种情况,那肯定就是你代码的问题了

额,没必要那么复杂吧。

你看下两个请求header,是不是第一个请求down掉了,排除下是不是两次点击导致的(如果是点击导致的,点击之后禁用dom元素的点击事件),或者是代码部分原因导致的。

顺带发下你请求的代码Fiddler捕获到的数据。

提交两次的原因大致有两种:
一,点击事件触发两次(这种情况不分网速快慢)
这种多是由于一些js插件造成的,需要google一下来处理,比较常见的是iscroll.js会造成事件执行两次,网上有很多方案.
二,是网速忙,用户等不及,多次点击
一定要在将要ajax前把按钮disabled掉,如果表单是可以多次提交的,在ajax后,再把disabled去掉。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn