如何使用SQL Server检查PHP中是否已经使用了用户名

时间:2018-07-14 18:42:13

标签: php sql sql-server azure azure-sql-database

我正在使用php和Azure数据库构建我自己的登录/注册网站,我无法弄清一件事:如何检查是否使用了用户名。我的代码不断返回:error retrieving username,但我不明白为什么以及如何解决。 这是我目前的注册代码:

<?php
    //Database connection file
    include_once("config.php");

    $username = $_POST['username'];
    $password = $_POST['password'];
    $conpassword = $_POST['conpassword'];

    $npassword = password_hash("$password", PASSWORD_DEFAULT);

    if($password !== $conpassword) {
        $_SESSION['errMsg'] = "Passwords don't match";
        header("location: ../register.php");
        exit();
    }

    $sql2 = "SELECT username FROM Gebruikers WHERE username = (?)";
    $params2 = array($username, SQLSRV_PARAM_IN);
    $stmt2 = sqlsrv_query($conn, $sql2, $params2);

    if ($stmt2 === false) {
        die(print_r(sqlsrv_errors(), true));
        exit();
    }

    $row_count = sqlsrv_num_rows($stmt2);

    if ($row_count != 0) {
        $_SESSION['errMsg'] = "Error retrieving username";
        header("location: ../register.php");
        exit();
    } else {
        if ($row_count > 0) {
            $_SESSION['errMsg'] = "Username is already used";
            header("location: ../register.php");
            exit();
        }
    }
}else{
    $sql = "INSERT INTO Gebruikers(username, password) VALUES (?, ?)";
    $params = array($username, $npassword);

    $stmt = sqlsrv_query( $conn, $sql, $params);

    if( $stmt === false ) {
        die( print_r( sqlsrv_errors(), true));
    }else{
        echo "Registration completed!";
        $_SESSION['errMsg'] = "Registration completed!";
        header("location: ../index.php");
        exit();
    }

?>

我希望有人知道我的问题的答案! 提前致谢!托马斯

2 个答案:

答案 0 :(得分:1)

许多方法可以做到这一点。也许最简单的方法是指定用户名在SQL Server中是唯一的。 您可以在SQL Server Management Studio中运行此命令

ALTER TABLE Gebruikers ADD CONSTRAINT unique_username UNIQUE (username)

如果您这样做,那一行

die( print_r( sqlsrv_errors(), true));

如果再次使用相同的用户名,将开始。

答案 1 :(得分:0)

您的用户名列应该是唯一的。在这种情况下,第二次插入将失败(如果名称已经存在,并且该列是唯一的,则无法再次插入)。在这种情况下,您有两个选择之一。您可以:

  1. 请提前查看以确保用户名免费

    select count(*) from Gebruikers where username = ?
    

如果查询未返回0,则使用名称。如果计数为0,则执行插入操作。如果为1,则添加错误以向用户显示。

  1. 将您的insert语句放在try-catch块中,并假定未使用用户名,如果使用了用户名,则让数据库插入失败,捕获异常并向用户显示错误(如果查询由于以下原因而失败)名称采用的列违反约束)。

编辑

我并不是说您的查询必须更改为我写的内容。从概念上讲,这两种方法如下。

创建用户表单提交的第一种可能性

check username availability with a query
if it's available
    insert a row for username,password
else
    add an error message / return an error response telling the user that the name is taken

创建用户表单提交的第二种可能性

try
    insert a row for username,password
catch constraint violation exception
    add an error message / return an error response telling the user that the name is taken

我个人认为第一种选择更好(向前看,看看用户名是否在那里)。

除此之外,您应该重新考虑您的设计。通读有点混乱。例如,类似

$addUserStatus = -1; // assume error
$username = $_POST['username'];
$password = $_POST['password'];
// confirm password
$conpassword = $_POST['conpassword'];

$errors = array();

// here you need to decide what a valid username is, surely not everything is valid
if (!validUsername($username)) {
    $errors[] = "Invalid username entered: " . $username;
}

if (!validPassword($password) {
    $errors[] = "Insert a password that is (your rules here)";
}

if ($password !== $conpassword) {
    $errors[] = "Passwords don't match";
}

if (count($errors) == 0) {
    // the user entered valid data, check to see if the username is taken
    $usernameStatus = available($username);
    if ($usernameStatus === 1) {
        $addUserStatus = addUser($username, $password);
        if ($addUserStatus === -1) {
            $errors[] = "An internal server error prevented the user from being added.";
        }
    } else if ($usernameStatus === 0) {
        $errors[] = "Username " . $username . " is taken, please choose another.";
    } else /* usernameStatus is -1 here */ {
        $errors[] = "Database access error, try again later".
    }
}

if (count($errors) === 0 && addUserStatus === 1) {
    // user was addded
} else {
    // do something with all the errors
}

function validUsername($username) {
    // TODO your logic here; what is a valid username for your app?
}

function validPassword($password) {
    // TODO your logic here; what password rules do you have? min characters? special characters?
}

function available($username) {
    // TODO implement a check to see if the username is available. Either select count like in my example and check that the value is 0 (it's available) or select * and see how many rows were returned (0 for available username)
    // here instead of just dying if $stmt === false (failure) either throw an exception or return an error code that makes sense to you, so for example instead of just returning true / false you could return 0 for not available, 1 for available and -1 for error; then you can handle this from the caller.
}

function addUser($username, $password) {
    // TODO hash the password, add the username and hashed password to the database
    // return 1 if user added, -1 for error
}