0

I have multiple forms on the same page that use the function generate_token(). I can only get one form to work if its the only form with the generate_token() function. I want to be able to have multiple forms on the same web page each with there own generate_token() function. But I just cant seem to get it to work when multiple forms on the same web page all have the generate_token() function. Can some one help me solve this problem. Thanks.

PHP Functions

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;
    }
}

Form Validation

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

    <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>
6
  • you cannot have the same id on both forms Commented May 23, 2017 at 22:53
  • sorry about that the id= should post-form-1 and so on. Commented May 23, 2017 at 22:54
  • the problem is, in your generate_token() it is setting the session token. This means the last time the function gets called that will set the session therefore the other times its overwritten Commented May 23, 2017 at 22:58
  • 1
    Turn your $_SESSION['token'] and $_SESSION['token_time'] into an array use in_array()? Commented May 23, 2017 at 22:58
  • I still can't seem to get it to work :( Commented May 23, 2017 at 23:06

1 Answer 1

1

In your code,

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

$_SESSION['token'] gets overwritten every time you call the function. You need to change it into an array, maybe even an associative array.

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

then, when you check it, you can keep the number of tokens to a reasonable level by using array_shift() or simply delete the token key in $_SESSION

for your function valid_token() you could use PHP command in_array() to look for it.

If you're doing this for CSRF protection, you're usually better off using code that has been around the block, tried and true. Check out OWASP for info about how to do CSRF protection.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.