我正在努力验证联系表格。我做了太多的过滤吗?

时间:2016-04-14 21:00:46

标签: javascript php forms validation security

我正在撰写联系表格 当用户在输入字段中键入时,我检查输入以查看它是否有效(在一个名为validateInput()的函数中使用javascript),如果它无效则会弹出一个bootstrap popover。

不需要lastName字段和主题字段。我有一个问题,我的正则表达式是否适合这些?(在window.onload中定义)

无论如何,如果用户提交表单,则会进行进一步的测试以查看该数据是否有效..(虽然已经检查过,但以防他们忽略了弹出窗口)。

如果在按下提交后数据确实有效,则表单数据将通过xmlhttp请求发送到contact_handler.php。 到达那里时,检查后期数据以查看它是否已设置..如果已设置,则我在不同的后期数据上使用filter_var函数。之后,我使用preg_replace将名称和消息字段过滤为一组有限的字符。

然后我调用contact_functions.php中定义的saveContactInfo()函数,该函数将数据插入数据库。 我的问题是:我是否进行了太多的数据过滤?是否存在做太多的事情?我只想确保数据安全。

这是我的代码。有很多评论,因为这是一项大学任务......

contact.html

<form>
    <div class="row">
        <div class="form-group">
                    <label for="firstname">Firstname*</label>
            <input type="text" class="form-control" id="first-name" maxlength="30" data-trigger="manual" data-placement="top" data-content="Must be at least 3 characters long, and must only contain letters and the following characters .'-" autofocus>
                </div>
        <div class="form-group">
                    <label for="lastname">Lastname</label>
                        <input type="text" class="form-control" id="last-name" maxlength="30" data-trigger="manual" data-placement="top" data-content="Must only contain letters and the following characters .'-" >
                </div>
        <div class="form-group">
            <label for="email">Email*</label>
                    <input type="email" class="form-control" id="email" maxlength="254" data-trigger="manual" data-placement="top" data-content="Must be a valid e-mail address.">
                </div>
        <div class="form-group">
                        <label for="subject">Subject</label>
                        <input type="text" class="form-control" id="subject" maxlength="200" data-trigger="manual" data-placement="top" data-content="Must only contain letters, numbers and the following characters .,'-?!=&quot;()">
                </div>              
                <div class="form-group">
                        <label for="message">Message*</label>
                        <textarea id="message" class="form-control" maxlength="1000" data-trigger="manual" data-placement="top" data-content="A message with a minimum of 15 characters is required. Must only contain letters, numbers and characters such as .,'-?!=&quot;()" rows="4"></textarea>
                </div>
        <div id="form-message" class="form-group">  
            <p></p>
        </div> 
        <!--give the button an id of submitButton so we can add a click event listener to it in our javascript-->
                <button id="submitButton" type="button"class="btn btn-orange"><i class="fa fa-envelope-o"></i> Submit</button>

    </div>                   
</form>

contact.html底部的javascript

<script>

//declare global variables
var firstNameRegex;
var lastNameRegex;
var subjectRegex;
var emailRegex;
var messageRegex;
var xmlhttpContact;

window.onload = function(){
    /*this function is implemented after the page is fully loaded.
     *the first name field should be a minimum of 3 characters and should only contain letters and certain special characters
     *such as full stop, apostrophe, and hyphen.
     */
    firstNameRegex = /^([A-Za-z .'-]{3,})$/;

    /*The last name field should be a minimum of 0 characters as it is not a required field, 
     *and should only contain letters and certain special characters such as full stop, apostrophe, and hyphen.
     */
    lastNameRegex = /^([A-Za-z .'-]{0,})$/;


    /*The subject field is optional so can therefore be a minium of 0 characters.
     *If any characters are entered in this field they should only be letters, numbers or certain special characters 
     *limited to the full stop, apostrophe, and hyphen characters.
     */
    subjectRegex = /^([A-Za-z0-9 .,'-?!="()]{0,})$/;

    //The email address entered by the user, will be tested against the following regular expression.
    //This regular expression for an email address is recommended in the W3C HTML5 specification. (See reference at top of this page.)
    emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;

    //The message entered by the user, will be tested against the following regular expression.
    //There is a minimum of 15 characters required in the message.
    messageRegex = /^([A-Za-z0-9 .,'-?!="()]{15,})$/; 


    //add a 'click' event listener to our submit button. When the button is pressed we will call the subitForm() function
    document.getElementById('submitButton').addEventListener('click', submitForm, false);

    //call the validateInput() function which we have defined below and pass the id of the input fields and their corresponding 
    //regular expression values as parameters.
    validateInput('first-name', firstNameRegex);
    validateInput('last-name', lastNameRegex);
    validateInput('subject', subjectRegex);
    validateInput('email', emailRegex);
    validateInput('message', messageRegex);

    //remove the form error and success messages when 'keypress' or 'focus' events occur on input or textarea fields.
    removeFormMessages();
}

function validateInput(inputID, regularExpression){
    /*This is a function which takes in the id of an input field or textarea and a regular expression as parameters.
     *In this function we test the value of the input field (or textarea) against the regular expression 
     *which we have defined for that input type to make sure the input is valid.
     *For example if we are taking in the users 'first name' as input, then we will test this against the 
     *regular expression we have defined for a valid first name (in the indow.onload function).
     *If it is NOT valid then we display a popover message to the user. 
     *If input IS valid then we hide the popover. This gives immediate feedback to the user during the process of filling
     *out the form.
     */

    //we listen for the following events on the input field or textarea that was passed as a parameter.
    //'keyup', 'keypress', 'blur', 'change' 
    //The input entered in that field is checked for validity when these events occur.
    //If it is not valid, then the popover with error message is displayed until input is validated.

    $('#' + inputID).on('keyup keypress blur change', function(){
        //store the value of our input field into a javascript variable called inputValue
        var inputValue = document.getElementById(inputID).value;

        //Now we test our inputValue against the appropriate regular expression (which we took in as a parameter).
        //the javascript test() function which we use here will return true if the input matches the regular expression
        //and false if not.
        //We store the boolean result into the variable isInputValid
        var isInputValid = regularExpression.test(inputValue);

        if(!isInputValid){  
        //If input is not valid go here
            if(!$(this).hasClass('isShowing')){
                //if our popover error does not have class isShowing then do the following
                //show popover and add class isShowing to the element so that we know what state it is in.
                $(this).popover('show');
                $(this).addClass('isShowing');
            }
            //else if our popover error is already showing then leave it showing (ie do nothing here).
        }else{
        //If input is valid go here
            if($(this).hasClass('isShowing')){
                //if our popover error has class isShowing then do the following
                //hide popover and remove isShowing class so we know it is hidden now
                $(this).popover('hide');
                $(this).removeClass('isShowing');
            }
            //else if our popover error is already hidden then leave it hidden.
        }
    });
}
function removeFormMessages(){
    /*This function listens for a 'keypress' or a 'focus' event on input and textarea fields
     *and when it detects these events it hides the form-message paragraph.
     *We do this because, If a user has submitted the form and then been notified that the 'form is invalid' 
     *and goes back to change his/her input then we assume they have seen the error message 
     *so we delete it so that the next time they are notified of something it will be easier to see.
     */
    $('input, textarea').on('keypress focus', function(){
        $("#form-message p").hide();
        $("#form-message p").removeClass('animated').removeClass('bounce');
        $("#form-message p").html('');
    });
}
function hideAllPopovers(){
    /*this function hides all popovers that are currently showing on input fields or textareas.
     *We will call this function after the form is submitted, if all fields are valid.
     */
    $('input, textarea').popover('hide');
    $('input, textarea').removeClass('isShowing');
}
function submitForm(){
    //get the values of all input and textarea fields in the contact form
    var firstName = document.getElementById('first-name').value;
    var lastName = document.getElementById('last-name').value;
    var email = document.getElementById('email').value;
    var subject = document.getElementById('subject').value;
    var message = document.getElementById('message').value;

    //we need to check the validity of the input values in case the user has ignored our popover error messages
    //therefore test (again) the values the user entered against regular expressions which we defined earlier for different types of input.
    //and store the boolean results into variables.
    var isfirstNameValid = firstNameRegex.test(firstName);
    var islastNameValid = lastNameRegex.test(lastName);
    var isSubjectValid = subjectRegex.test(subject); 
    var isEmailValid = emailRegex.test(email); 
    var isMessageValid = messageRegex.test(message);

    if((!isfirstNameValid) || (!islastNameValid) ||(!isEmailValid) ||(!isSubjectValid) || (!isMessageValid)){
        //If any of the values entered to the input fields are invalid then show an error message to the user.
        //And do not allow the form to be submitted
        //We use the error-text class for red text.
        $("#form-message p").html('<span class="error-text"><i class="fa fa-exclamation-triangle"></i> The form is not valid!</span>');
        $("#form-message p").show();
        $("#form-message p").addClass('animated').addClass('bounce');
    }else{
        //If form input is valid then firstly hide any popovers which are showing
        hideAllPopovers();

        //then we create a new xmlhttp request.
        xmlhttpContact = createXHR();

        xmlhttpContact.onreadystatechange = contactCallback; //when the response comes back call the contactCallback function
        //Send our form values to the contact_handler.php page by POST 
        xmlhttpContact.open("POST", "contact_handler.php" ,true);   
        xmlhttpContact.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        //send our variables to the contact_handler.php page by POST
        xmlhttpContact.send("firstName=" + firstName + "&lastName=" + lastName + "&email=" + email + "&subject=" + subject + "&message=" + message);

    }
}

function contactCallback(){
    //this function will be called when we receive a response back from the xmlhttp request.
    if(xmlhttpContact.readyState == 4 && xmlhttpContact.status == 200){

        //store the response text into a variable called message.
        var message = xmlhttpContact.responseText;

        //clear any text in the input fields.
        $('input, textarea').val('');
        //insert our message to the form-message paragraph tag
        $("#form-message p").html('<i class="fa fa-check"></i> ' + message);
        $("#form-message p").show();
        //we use the bootstrap animation classes to create an animation on the message text.
        $("#form-message p").addClass('animated').addClass('bounce');

    }
}
</script>

contact_handler.php

<?php
//check if all the required fields are set
if(isset($_POST['firstName']) && isset($_POST['email']) && isset($_POST['message'])){
    //collect the post data if the contact form has been submitted and store it into local variables

    //Remove all HTML tags from $_POST["firstName"] and store it into variable $firstName
    $firstName = filter_var($_POST["firstName"], FILTER_SANITIZE_STRING); 

    if(isset($_POST['lastName'])){
        //check if lastName isset before filtering it.
        //Remove all HTML tags from $_POST["lastName"] and store it into variable $lastName
        $lastName = filter_var($_POST["lastName"], FILTER_SANITIZE_STRING); 
    }

    //Remove illegal characters from $_POST["email"]
    $email = filter_var($_POST["email"], FILTER_SANITIZE_EMAIL); 

    if(isset($_POST['subject'])){
        //check if subject isset before filtering it.
        //Remove all HTML tags from $_POST["subject"] and store it into variable $subject
        $subject = filter_var($_POST["subject"], FILTER_SANITIZE_STRING); 
    }

    //Remove all HTML tags from $_POST["message"] and store it into variable $message
    $message = filter_var($_POST["message"], FILTER_SANITIZE_STRING); 

    //do further filtering with preg_replace for extra security.
    $firstName = preg_replace("#[^A-Za-z .'-]#i", "", $firstName); //filter everything but letters and a few special characters.
    $lastName = preg_replace("#[^A-Za-z .'-]#i", "", $lastName); //filter everything but letters and a few special characters.
    $subject = preg_replace("#[^A-Za-z0-9 .,'-?!=\"()]#i", "", $subject); //filter everything but numbers, letters and a few special characters.
    $message = preg_replace("#[^A-Za-z0-9 .,'-?!=\"()]#i", "", $message); //filter everything but numbers, letters and a few special characters.


    //store the boolean result of saveContactInfo function into a variable called $messageSent
    $messageSent = saveContactInfo($firstName, $lastName, $email, $subject, $message, $pdoConnection);//this method is defined in contact_functions.php
    if($messageSent){
        //if saveContactInfo returns true then we know the data has been entered to the database so we inform the user that
        //the message has been sent. This message will be echoed back to our ajax callback method in contact.html 
        //where we will insert it to the HTML.
        echo 'Your Message has been sent!!';
    }
}
?>

contact_functions.php

<?php
function saveContactInfo($firstName, $lastName, $email, $subject, $message, $pdoConnection){
    $messageTime = time(); //Get timestamp of current time and store it into a variable

    try{
        $query ="INSERT INTO contact_info (firstName, lastName, email, subject, message, messageTime) VALUES (:firstName, :lastName, :email, :subject, :message, :messageTime)";
        $statement = $pdoConnection->prepare($query);
        $statement->bindValue(':firstName', $firstName, PDO::PARAM_STR); 
        $statement->bindValue(':lastName', $lastName, PDO::PARAM_STR); 
        $statement->bindValue(':email', $email, PDO::PARAM_STR); 
        $statement->bindValue(':subject', $subject, PDO::PARAM_STR);
        $statement->bindValue(':message', $message, PDO::PARAM_STR); 
        $statement->bindValue(':messageTime', $messageTime, PDO::PARAM_STR); 
        $statement->execute();
        return true;
    }catch(PDOException $e){
        //throw new pdoDbException($e); 
        return "Error message " . $e->getMessage();
    }
}
?>

1 个答案:

答案 0 :(得分:1)

  

有没有做太多的事情?

当然可以,任何事情都可以做到荒谬的时间而变得过多。&#34;

  

我做了太多数据过滤吗?

我会说是,但问题很空洞。我将此解释为“我是否正在进行最有意义的验证?&#34;”。您正在进行太多验证,因为您正在验证前端和后端。对于将要发送到contact_handler.php的查询字符串的内容,您可能只想在后端执行所有操作,因为任何人都可以绕过您的javascript并手动输入查询字符串。< / p>

这并不意味着不在前端进行验证。在实践中,我通常只在前端进行一种类型的验证,以确保填写所有表单的字段。

我在后端对长度和内容进行的所有验证,发回对xhr请求的响应中的任何错误。当然,重新验证查询字符串中字段的存在是必须的,因为任何人都可以手动发送带有意外查询字符串的请求。

我避免了前端验证,直到后端坚如磐石。