Home  >  Article  >  Backend Development  >  javascript - Mobile form submission page, if the network is slow, the form will be submitted twice

javascript - Mobile form submission page, if the network is slow, the form will be submitted twice

WBOY
WBOYOriginal
2016-10-22 00:14:241344browse

The mobile website submission page works normally when the network is good. When the network is slow, the mobile page will keep loading. However, Fiddler captures the same content and submits it twice. How to avoid this situation?

Reply content:

The mobile website submission page works normally when the network is good. When the network is slow, the mobile page will keep loading. However, Fiddler captures the same content and submits it twice. How to avoid this situation?

My approach is to generate a token on the server and verify the token when submitting. This is the first verification. The second verification is to set the submit button to disabled when the form is submitted. Generally, the second verification is done. That’s it

<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 verification class

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

        $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->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 < $length; ++$i )
            $string .= $seed{intval( mt_rand( 0.0, $max ) )};

        return $string;
    }

}
?></code>

It must be clicked once and submitted once. It is impossible for you to click once and submit twice because of a slow network - how can the triggering of the event be like rootless water? If this is the case, it must be a problem with your code

Well, it doesn’t need to be so complicated.

Look at the two requests

header. Is the first request down? Check whether it is caused by two clicks (if it is caused by clicks, disable the click event of the dom element after clicking), or It is caused by part of the code.

By the way, please send me your

requested code and the data captured by Fiddler.

There are roughly two reasons for submitting twice:

First, the click event is triggered twice (this situation does not depend on the speed of the network)
This is mostly caused by some js plug-ins, which need to be googled to deal with, which is relatively common Yes
iscroll.js will cause the event to be executed twice. There are many solutions on the Internet. Second, the network speed is busy and the user cannot wait. If you click
multiple times, you must turn off the button
disabled before ajax. If The form can be submitted multiple times. After ajax, remove disabled.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn