如何在php中实现令牌基表单提交

时间:2017-04-20 10:12:11

标签: php mysql

我一直在尝试在php中创建自己的OOP样式注册登录系统,我已经实现了一些安全功能,如使用htmlentites()的xss保护,为SQL注入保护准备方法和基于令牌的表单提交csrf保护(目前我是卡在我的代码中实现这个功能,在提交表单数据时获得"无效的令牌" 但我不太确定安全网站是否足以为真实的现场项目制作。我希望您查看我的代码,请帮助我解决在我的代码中实现令牌基本表单提交的问题,并建议我在当前代码中改进编码风格的方法。

这是我的register.php页面

<?php
//error_reporting(0);
session_start();


if(isset($_POST["submit"])){
    include "Db_handlers.php";
    $db = new DbHandler();
    $res = $db->createUser($_POST["name"], $_POST["email"], $_POST["password"], $_POST["re-password"], $_POST['token']);
    print_r($res);
    /*if($res){
        echo "test";
    }
    else {
        echo $res;
    }*/
}
$token = $_SESSION['token'] = md5(uniqid(mt_rand(),true));

?>

<form action="<?=$_SERVER['PHP_SELF'];?>" method="post">
    <div class="field">
        <label for="name">Name:</label>
        <input type="text" name="name" value="" />      
    </div>
    <div class="field">
        <label for="email">Email:</label>
        <input type="text" name="email" value="" />     
    </div>
    <div class="field">
        <label for="password">Password:</label>
        <input type="password" name="password" value="" />      
    </div>
    <div class="field">
        <label for="repassword">Re-Password:</label>
        <input type="password" name="re-password" value="" />       
    </div>
    <input type="hidden" name="token" value="<?=$token;?>"/>
    <input type="submit" name="submit" value="submit" />
</form>

这是我的数据库处理程序类

 <?php 
    require 'functions.php';

    class DbHandler {

    private $conn;

    public function __construct() {

    try{

    $this->conn = new PDO("mysql:host=127.0.0.1;dbname=task_manager", "root" , "");

    // echo "Connected";
    }
    catch(PDOException $e){
        //die($e->getMessage());
        echo "Connection Failed: ".$e->getMessage();
    }
    }

    public function createUser($name, $email, $password, $repassword, $utoken) {
    // $error = array();
    $error = '';
    $required_fields = array($name, $email, $password, $repassword);
    $fields = array_map('trim', $required_fields);
    if (in_array(null, $fields)) {
        $error = 'Fields marked with an asterisk are required';
    }

    else if($this->valid_token($utoken) == false){
       $error = "Invalid Token...!!!";
    }

    else if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
       $error = 'Please enter a valid email address !';
    }

    else if(strlen($password) < 6){
        $error = "Password must be atleast 6 characters"; 
    }

    else if($password !== $repassword){
        $error = "Password do n\' t match!!";
    }
    else{
       $name = escape($name);
       $email = escape($email);
       $password_hash = escape($password);
       // First check if user already existed in db
       if (!$this->isUserExists($email)) {
       // Generating password hash
       $password_hash = password_hash($password, PASSWORD_DEFAULT, ['cost'=>12]);
      // insert query
       $stmt = $this->conn->prepare("INSERT INTO users(name, email, password_hash, status) values(:name, :email, :password_hash, 1)");
      //$stmt->bind_param("ssss", $name, $email, $password_hash);
      $result = $stmt->execute(array(':name' => $name,':email' => $email,':password_hash' => $password_hash));;
     //$stmt->close();
     // Check for successful insertion
     if ($result) {
     // User successfully inserted
         return $result;
      } else {
      // Failed to create user
        $error = "Failed to create user";
      }
      } else {
         // User with same email already existed in the db
         $error = "User already exists";
      }
      }
        return $error;
    }




    private function isUserExists($email) {
        $stmt = $this->conn->prepare("SELECT id from users WHERE email = :email");
        //$stmt->bind_param("s", $email);
        $stmt->execute(array(':email' => $email));
        //$stmt->bind_result();
        $num_rows = $stmt->rowCount();
        //$stmt->close();
        return $num_rows > 0;
    }


    public function valid_token($token){
       if(!isset($_SESSION['token']) || $token != $_SESSION['token'])
       return false; 
    }
    }

1 个答案:

答案 0 :(得分:0)

你的代码真的难以阅读......你应该正确地缩进它。

回到你的问题。看来,如果您的令牌不正确,您只需返回false,但如果错误,则忘记返回true。如果您什么都不返回,则隐式返回null,其评估为false。我想,如果您的更改valid_token如下:

,您的代码就可以运行
public function valid_token($token){
    return isset($_SESSION['token']) && $token == $_SESSION['token'];
}