PHP多表单验证问题

时间:2017-05-23 22:49:47

标签: php validation

我在同一页面上有多个使用函数generate_token()的表单。如果它是唯一具有generate_token()函数的表单,我只能得到一个表单。我希望能够在同一个网页上拥有多个表单,每个表单都有自己的generate_token()函数。但是,当同一网页上的多个表单都具有generate_token()函数时,我似乎无法使其工作。有人可以帮我解决这个问题。感谢。

PHP函数

function real_domain(){
    if(!isset($_SERVER['HTTP_REFERER'])){
        return false;
    } else {
        $referer_host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
        $server_host = $_SERVER['HTTP_HOST'];

        return ($referer_host == $server_host) ? true : false;
    }
}

function request_is_post(){
    return filter_input(INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING) === 'POST';
}

function token(){
    return md5(uniqid(rand(), true));
}

function generate_token(){
    $token = token();
    $_SESSION['token'] = $token;
    $_SESSION['token_time'] = time();
    return $token;
}

function destroy_token(){
    $_SESSION['token'] = null;
    $_SESSION['token_time'] = null;
    return true;
}

function valid_token(){
    if(isset($_POST['token']) && !is_array($_POST['token'])){
        if(isset($_POST['token'])){
            $user_token = $_POST['token'];

            if(isset($_SESSION['token'])){
                $stored_token = $_SESSION['token'];
                return $user_token === $stored_token;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        foreach($_POST['token'] as $token){
            if(isset($token)){
                $user_token = $token;

                if(isset($_SESSION['token'])){
                    $stored_token = $_SESSION['token'];
                    return $user_token === $stored_token;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    }
}

function token_time(){
    $expire_token = 60 * 60 * 24;

    if(isset($_SESSION['token_time'])){
        $stored_time = $_SESSION['token_time'];
        return ($stored_time + $expire_token) >= time();
    } else {
        destroy_token();
        return false;
    }
}

表单验证

if(real_domain()){
    if(request_is_post()){
        if(valid_token()){
            if(token_time()){
                $errors = '';
                $success = '';

                if(isset($_POST['submit_comment'])){
                        $post_id = filter_numbers($_POST['post_id']);
                        $comment = filter_members_string($_POST['comment']);

                        if(!empty($_POST['comment'])){
                            if(empty($comment)){
                                $errors .= '<p class="error">&#x2731; Error.</p>';
                            } else {
                                if(strlen(html_entity_decode($comment, ENT_NOQUOTES, 'UTF-8')) >= 5001){
                                    $errors .= '<p class="error">&#x2731; Error.</p>';
                                } else {
                                    if($_POST['comment'] !== $comment){
                                        $errors .= '<p class="error">&#x2731; Error.</p>';
                                    } else {
                                        $success .= '<p class="success">&#x2714; Your comment was posted.</p>';
                                    }
                                }
                            }
                        }

                        if(!empty($success) && empty($errors)){
                            $query = "INSERT `post_comments` (`post_id`, `member_id`, `comment`, `date_created`)
                                      VALUES('$post_id ', '" . $_SESSION['member_id'] . "', '$comment_value', NOW())";
                            mysqli_query(database(), $query);
                        }

                        if(empty($success) && empty($errors)){
                            $errors .= '<p class="error">&#x2731; Your comment was not posted.</p>';
                        }           
                }
            }
        }
    }
}

HTML表单

    <form method="post" action="" class="post-form">
        <fieldset>
            <ol>
                <li><label for="post-info-2" class="post-header">Post</label></li>
                <li><textarea name="post" id="post-info-2"></textarea></li>
            </ol>
        </fieldset>
        <fieldset>  
            <ol>
                <li><input type="submit" name="submit_post" value="Submit Post" class="submit-post" /><input type="hidden" name="token" value="<?php echo generate_token(); ?>" /></li>
            </ol>
        </fieldset>
    </form>

    <form method="post" action="" class="post-form">
        <fieldset>
            <ol>
                <li><label for="post-info" class="post-header">Post</label></li>
                <li><textarea name="post" id="post-info"></textarea></li>
            </ol>
        </fieldset>
        <fieldset>  
            <ol>
                <li><input type="submit" name="submit_post" value="Submit Post" class="submit-post" /><input type="hidden" name="token" value="<?php echo generate_token(); ?>" /></li>
            </ol>
        </fieldset>
    </form>

1 个答案:

答案 0 :(得分:1)

在您的代码中,

function generate_token(){
    $token = token();
    $_SESSION['token'] = $token;
    $_SESSION['token_time'] = time();
    return $token;
}
每次调用该函数时,

$_SESSION['token']都会被覆盖。您需要将其更改为数组,甚至可能是关联数组。

function generate_token() {
  $token = token();
  $_SESSION['token'][] = array('value' => $token, 'time' => time());
  return $token;
}

然后,当您检查它时,您可以使用array_shift()将令牌数量保持在合理的水平,或者只需删除$_SESSION中的令牌密钥

对于function valid_token(),您可以使用PHP命令in_array()来查找它。

如果您正在为CSRF保护做这件事,那么通常最好使用围绕该块的代码,尝试并且是真的。查看OWASP,了解有关如何进行CSRF保护的信息。