如何使用php重定向到另一个html文件 [英] How to redirect to another html file using php

查看:35
本文介绍了如何使用php重定向到另一个html文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个表单来验证存在于 MySQL 数据库中的用户名和密码(使用 UwAmp) 它有一个名为 users 的数据库 和一个名为 userdetails 的表,它有 2 列 UsernamePassword 都包含 user>pass 分别作为数据.

我知道我目前没有使用最好的最新安全方法(我想在这样做后了解这一点).

当该页面保留在 login.php 上时,无论详细信息是否正确,在这两种情况下,页面上的所有内容都会消失.

顺便说一句,我可能会对此感到困惑,但是有没有一种方法可以将密码存储在 UwAmp 数据库中,而不仅仅是纯文本.我可以加密吗?

我有以下 PHP 文件

HTML 文件

错误.

( ! ) 警告:mysql_fetch_assoc() 期望参数 1 是资源,布尔值在 C:\Users\user\Documents\examplePHP\UAMP\UwAmp\www\techTest\php\login.php 中给出1( ! ) 注意:未定义变量:第 18 行 C:\Users\user\Documents\examplePHP\UAMP\UwAmp\www\techTest\php\login.php 中的 check_username

解决方案

简短说明:

  • 警告 mysql_fetch_assoc() 期望参数 1 为资源,给定布尔值 ... 可能是因为 mysqli_query 返回 FALSE 而引发的 -用于表示失败的值 - 而不是 mysqli_result (请参阅).为什么会出现这种情况,这取决于您自己找出来.我没有看到任何可能导致它的疏忽.
  • 通知 Undefined variable: check_username ... 在 db 表中找不到记录的情况下引发.在这种情况下,while 语句中的变量定义和值分配不会发生.因此,在 while 语句之外,变量 $check_username$check_password 被识别"为未定义.
  • 不要忘记在重定向代码之后调用 exit(),例如发送 Location 响应标头后.

现在,你的第一个大问题是,你不使用任何 准备语句 以避免SQL注入.因此,您绝对应该使用准备 sql 语句所涉及的函数,而不是 mysqli_query,并为其中找到的最终参数标记注入值.

第二个大问题实际上是,如果您决定以明文或不安全的形式(如 md5)保存密码.密码应该是高度加密的.对于此任务,我建议您使用 password_hash 函数- 使用 PASSWORD_BCRYPT 选项(定义 Blowfish 哈希算法的常量),或使用 PASSWORD_ARGON2I 选项(定义 Argon2 哈希算法并从 PHP 7.2.0 开始引入).您应该彻底阅读 password_hash 和使用的常量的文档.您可能想阅读这篇文章

我在下面写了一个代码版本,实现了上面两点,希望能带来更多的清晰.我使用了面向对象的 mysqli 库(而不是程序库)和我的命名/编码约定(包括 db 表) - 所以,因为我会在我的项目中应用它们.它还包含服务器端的凭据验证部分.实际上是必需的步骤.

原则上,在创建 login.php 代码之前,您应该创建一个页面,负责将用户凭据保存在 db 表中.在该页面(例如create-user.php)中,将为给定的密码创建一个密码哈希(使用password_hash 函数)并保存.散列将是至少 60 个任意字符的字符串.相关页面代码如下所示:

//...$username = $_POST['username'];$password = $_POST['password'];//从发布的密码创建一个哈希.$passwordHash = password_hash($password, PASSWORD_BCRYPT);$sql = 'INSERT INTO user_credentials (username, password) VALUES (?, ?)';$statement = $connection->prepare($sql);$statement->bind_param('ss', $username, $passwordHash);$statement->execute();//...

但是,为了暂时缩短任务,您可以在 PHP 中从值 pass 创建一个密码哈希值,然后手动复制并保存它以及 user 值:

//从pass"值创建一个散列.$passwordHash = password_hash('pass', PASSWORD_BCRYPT);回声 $passwordHash;

建议:对于应用错误/异常处理,您可以查看thisthis 教程文章.

最后,这里是我使用的登录页面、数据库连接代码、表结构和文件系统结构:

登录.php

prepare($sql);/** 为参数标记 (?) 中的绑定变量* 传递给 prepare() 的 SQL 语句.首先* bind_param() 的参数是一个包含一个的字符串* 或多个指定类型的字符* 对应的绑定变量.** @link http://php.net/manual/en/mysqli-stmt.bind-param.php*/$statement->bind_param('s', $username);/** 执行准备好的SQL语句.* 当执行任何存在的参数标记时* 自动替换为适当的数据.** @link http://php.net/manual/en/mysqli-stmt.execute.php*/$statement->execute();/** 从准备好的语句中获取结果集.** 注意事项:* 仅适用于 mysqlnd(MySQL 本地驱动程序")!如果这* 未安装,则取消注释中的extension=php_mysqli_mysqlnd.dll"* PHP 配置文件 (php.ini) 并重新启动 Web 服务器(我假设是 Apache)和* mysql 服务.或者改用以下函数:* mysqli_stmt::store_result + mysqli_stmt::bind_result + mysqli_stmt::fetch.** @link http://php.net/manual/en/mysqli-stmt.get-result.php* @link https://stackoverflow.com/questions/8321096/call-to-undefined-method-mysqli-stmtget-result*/$result = $statement->get_result();/** 将凭据提取到关联数组中.* 如果没有找到记录,操作返回NULL.*/$credentials = $result->fetch_array(MYSQLI_ASSOC);/** 释放与结果相关的内存.你应该* 不再需要时总是释放您的结果.** @link http://php.net/manual/en/mysqli-result.free.php*/$result->close();/** 关闭准备好的语句.它还释放语句句柄.* 如果语句有待处理或未读结果,则取消它们* 以便可以执行下一个查询.** @link http://php.net/manual/en/mysqli-stmt.close.php*/$statement->close();/** 关闭之前打开的数据库连接.不是很需要,* 因为 PHP 在脚本处理完成后关闭连接.** @link http://php.net/manual/en/mysqli.close.php*/$connection->close();if (isset($credentials) && $credentials) {//找到记录.$fetchedUsername = $credentials['username'];$fetchedPasswordHash = $credentials['password'];/** 将发布的用户名与保存在 db 中的用户名和发布的用户名进行比较* 使用password_hash 将密码哈希保存在db 中的密码.** @link https://secure.php.net/manual/en/function.password-verify.php* @link https://secure.php.net/manual/en/function.password-hash.php*/如果 ($username === $fetchedUsername &&密码验证($password,$fetchedPasswordHash)){header('位置:welcome.html');出口();} 别的 {$errors[] = '无效的凭据.请再试一次.';}} 别的 {$errors[] = '没有找到给定用户的凭据.';}}}echo '

'.print_r(password_hash('pass', PASSWORD_BCRYPT), TRUE) .'</pre>';?><!DOCTYPE html><头><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes"/><meta charset="UTF-8"/><!-- 以上 3 个元标记必须排在头上 --><title>演示 - 登录</title><script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script><script type="text/javascript">$(document).ready(function () {$('#username').focus();});函数validateForm(){返回真;}<style type="text/css">身体 {填充:30px;}标签 {显示:块;字体粗细:400;}输入[类型=文本"],输入[类型=密码"] {显示:块;底边距:20px;}按钮 {显示:块;填充:7px 10px;背景色:#8daf15;颜色:#fff;边界:无;}.messages {底边距:20px;}.messages .error {颜色:#c00;}</风格><身体><div class="messages"><?php如果(isset($错误)){foreach ($errors as $error) {?><div class="错误"><?php echo $error;?>

<?php}}?>

<div class="form_login"><form name="credentials" action="" method="post" onsubmit="return validateForm();"><label for="username">用户名:</label><input type="text" id="username" name="username" value="<?php echo isset($username) ? $username : ''; ?>"><label for="password">密码:</label><input type="password" id="password" name="password" value="<?php echo isset($password) ? $password : ''; ?>"><button type="submit" name="submit" value="submit">提交</表单>

</html>

包括/connection.php

report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);/** 创建一个新的数据库连接.** @see http://php.net/manual/en/mysqli.construct.php*/$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE, PORT);

创建表语法

创建表`user_credentials`(`id` int(11) 无符号 NOT NULL AUTO_INCREMENT,`username` varchar(100) 默认为空,`password` varchar(255) 默认为空,主键(`id`)) 引擎=InnoDB 默认字符集=utf8;

文件系统结构

包括连接.php登录.php欢迎.html

I'm trying to create a form that authenticates a username and password that exists in a MySQL database (using UwAmp) It has a database called users and a table called userdetails that has 2 columns Username and Password both contain user and pass respectively as data.

I know I'm not using the best most up to date security methods at the moment (I want to learn that after doing this).

At the moment that page remains on login.php regardless if the details are correct, in both circumstances, everything disappears on the page.

As a side note I may be getting this confused but is there a way of storing a password in a UwAmp database that isn't just plain text. Can I encrypt it?

I have the following PHP file

<?php

    include_once '/includes/db-connect.php'; //Connect to the database
    if(isset($_POST["Username"], $_POST["Password"])) 
    {     

        $name = $_POST["Username"]; 
        $password = $_POST["Password"]; 

        $result1 = mysqli_query($conn, "SELECT Username, Password FROM userdetails WHERE Username = '".$name."' AND  Password = '".$password."'");

        while($row=mysql_fetch_assoc($result1))
        {
           $check_username=$row['Username'];
           $check_password=$row['Password'];
        }

        if($username == $check_username && $password == $check_password) {
           header("Location: welcomePage.html");
        }
        else { 
           echo "No match.";
        }
    }

HTML file

<div class="form_login">


<form name="credentials" action="php/login.php" onsubmit="return validateForm();" method="post">
             Username:<br>
  <input type="text" name="Username" value=""><br>
  Pasword:<br>
  <input type="password" name="Password" value=""><br><br>
  <input type="submit" value="Submit">
</form>


          </div>

errors.

( ! ) Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in C:\Users\user\Documents\examplePHP\UAMP\UwAmp\www\techTest\php\login.php on line 1

( ! ) Notice: Undefined variable: check_username in C:\Users\user\Documents\examplePHP\UAMP\UwAmp\www\techTest\php\login.php on line 18

解决方案

Short notes first:

  • The warning mysql_fetch_assoc() expects parameter 1 to be resource, boolean given ... was probably raised because mysqli_query returned FALSE - the value used to signalize a failure - instead of a mysqli_result (see this). Why you have this situation, it's up to you to find out. I didn't saw any inadvertence which might have produced it.
  • The notice Undefined variable: check_username ... is raised in the case when no record is found in the db table. In that case, the variable definitions and the values assignation inside of while statement don't take place. Therefore, outside of while statement the variables $check_username and $check_password are "recognized" as not defined.
  • Don't forget to call exit() after the redirectioning code, e.g. after sending the Location response header.

Now, your first big problem is, that you don't use any prepared statements in order to avoid SQL injection. So, instead of mysqli_query, you should definitely use the functions involved in preparing an sql statement - in this case yours - and injecting the values for eventual parameter markers found in it.

The second big problem would be, indeed, if you would decide to save the password in clear text, or in a not secure form - like md5. The password should be strongly encrypted. For this task I would recommend you to use the password_hash function - either with the PASSWORD_BCRYPT option (a constant defining the Blowfish hashing algorithm), or with the PASSWORD_ARGON2I option (constant defining the Argon2 hashing algorithm and introduced as of PHP 7.2.0). You should thoroughly read the documentation of password_hash and of the used constants. You might maybe want to read this post too.

I wrote a code version below, implementing the two points above, in the hope that it will bring more clarity. I used the object-oriented mysqli library (instead of the procedural one) and my naming/coding conventions though (inclusive for the db table) - so, as I would apply them in my project. It also contains a credentials validation part on the server-side. A required step, actually.

In principle, before creating a login.php code, you should create a page responsible with saving user credentials in the db table. In that page (create-user.php for example), for the given password a password hash will be created (using the password_hash function) and saved. The hash will be a string of minimum 60 aleatory characters. The relevant page code would look like this:

//...

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

// Create a hash from the posted password.
$passwordHash = password_hash($password, PASSWORD_BCRYPT);

$sql = 'INSERT INTO user_credentials (username, password) VALUES (?, ?)';

$statement = $connection->prepare($sql);
$statement->bind_param('ss', $username, $passwordHash);
$statement->execute();

//...

But, in order to shorten the task for now, you can create in PHP a password hash from the value pass and copy and save it manually, along with the user value:

// Create a hash from the "pass" value.
$passwordHash = password_hash('pass', PASSWORD_BCRYPT);
echo $passwordHash;

Suggestion: for applying error/exception handling you could take a look at this and this tutorial articles.

At last, here is the login page, the db connection code, the table structure and the file system structure that I used:

login.php

<?php
/* Don't use include_once to include the connection page! */
require 'includes/connection.php';

// Operations upon form submission.
if (isset($_POST['submit'])) {
    // Validate username.
    if (!isset($_POST['username']) || empty($_POST['username'])) {
        $errors[] = 'Please provide the username.';
    } /* Other validations here using "else if". For example on username length. */

    // Validate password.
    if (!isset($_POST['password']) || empty($_POST['password'])) {
        $errors[] = 'Please provide the password.';
    } /* Other validations here using "else if". For example on password length. */

    if (!isset($errors)) { // No errors.
        // Get posted credentials.
        $username = $_POST['username'];
        $password = $_POST['password'];

        /*
         * The SQL statement to be prepared. Notice the so-called markers, 
         * e.g. the "?" signs. They will be replaced later with the 
         * corresponding values when using mysqli_stmt::bind_param.
         * 
         * @link http://php.net/manual/en/mysqli.prepare.php
         */
        $sql = 'SELECT username, password 
                FROM user_credentials 
                WHERE username = ? 
                LIMIT 1';

        /*
         * Prepare the SQL statement for execution - ONLY ONCE.
         * 
         * @link http://php.net/manual/en/mysqli.prepare.php
         */
        $statement = $connection->prepare($sql);

        /*
         * Bind variables for the parameter markers (?) in the 
         * SQL statement that was passed to prepare(). The first 
         * argument of bind_param() is a string that contains one 
         * or more characters which specify the types for the 
         * corresponding bind variables.
         * 
         * @link http://php.net/manual/en/mysqli-stmt.bind-param.php
         */
        $statement->bind_param('s', $username);

        /*
         * Execute the prepared SQL statement.
         * When executed any parameter markers which exist will 
         * automatically be replaced with the appropriate data.
         * 
         * @link http://php.net/manual/en/mysqli-stmt.execute.php
         */
        $statement->execute();

        /*
         * Get the result set from the prepared statement.
         * 
         * NOTA BENE:
         * Available only with mysqlnd ("MySQL Native Driver")! If this 
         * is not installed, then uncomment "extension=php_mysqli_mysqlnd.dll" in 
         * PHP config file (php.ini) and restart web server (I assume Apache) and 
         * mysql service. Or use the following functions instead:
         * mysqli_stmt::store_result + mysqli_stmt::bind_result + mysqli_stmt::fetch.
         * 
         * @link http://php.net/manual/en/mysqli-stmt.get-result.php
         * @link https://stackoverflow.com/questions/8321096/call-to-undefined-method-mysqli-stmtget-result
         */
        $result = $statement->get_result();

        /*
         * Fetch the credentials into an associative array.
         * If no record is found, the operation returns NULL.
         */
        $credentials = $result->fetch_array(MYSQLI_ASSOC);

        /*
         * Free the memory associated with the result. You should 
         * always free your result when it is not needed anymore.
         * 
         * @link http://php.net/manual/en/mysqli-result.free.php
         */
        $result->close();

        /*
         * Close the prepared statement. It also deallocates the statement handle.
         * If the statement has pending or unread results, it cancels them 
         * so that the next query can be executed.
         * 
         * @link http://php.net/manual/en/mysqli-stmt.close.php
         */
        $statement->close();

        /*
         * Close the previously opened database connection. Not really needed, 
         * because PHP closes the connection after script processing finishes.
         * 
         * @link http://php.net/manual/en/mysqli.close.php
         */
        $connection->close();

        if (isset($credentials) && $credentials) { // Record found.
            $fetchedUsername = $credentials['username'];
            $fetchedPasswordHash = $credentials['password'];

            /*
             * Compare the posted username with the one saved in db and the posted
             * password with the password hash saved in db using password_hash.
             * 
             * @link https://secure.php.net/manual/en/function.password-verify.php
             * @link https://secure.php.net/manual/en/function.password-hash.php
             */
            if (
                    $username === $fetchedUsername &&
                    password_verify($password, $fetchedPasswordHash)
            ) {
                header('Location: welcome.html');
                exit();
            } else {
                $errors[] = 'Invalid credentials. Please try again.';
            }
        } else {
            $errors[] = 'No credentials found for the given user.';
        }
    }
}

echo '<pre>' . print_r(password_hash('pass', PASSWORD_BCRYPT), TRUE) . '</pre>';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo - Login</title>

        <script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>

        <script type="text/javascript">
            $(document).ready(function () {
                $('#username').focus();
            });

            function validateForm() {
                return true;
            }
        </script>

        <style type="text/css">
            body {
                padding: 30px;
            }

            label {
                display: block;
                font-weight: 400;
            }

            input[type="text"],
            input[type="password"] {
                display: block;
                margin-bottom: 20px;
            }

            button {
                display: block;
                padding: 7px 10px;
                background-color: #8daf15;
                color: #fff;
                border: none;
            }

            .messages {
                margin-bottom: 20px;
            }

            .messages .error {
                color: #c00;
            }
        </style>
    </head>
    <body>

        <div class="messages">
            <?php
            if (isset($errors)) {
                foreach ($errors as $error) {
                    ?>
                    <div class="error">
                        <?php echo $error; ?>
                    </div>
                    <?php
                }
            }
            ?>
        </div>

        <div class="form_login">
            <form name="credentials" action="" method="post" onsubmit="return validateForm();">
                <label for="username">Username:</label>
                <input type="text" id="username" name="username" value="<?php echo isset($username) ? $username : ''; ?>">

                <label for="password">Password:</label>
                <input type="password" id="password" name="password" value="<?php echo isset($password) ? $password : ''; ?>">

                <button type="submit" name="submit" value="submit">
                    Submit
                </button>
            </form>
        </div>

    </body>
</html>

includes/connection.php

<?php

// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'users');
define('USERNAME', 'youruser');
define('PASSWORD', 'yourpass');

/*
 * Enable internal report functions. This enables the exception handling, 
 * e.g. mysqli will not throw PHP warnings anymore, but mysqli exceptions 
 * (mysqli_sql_exception).
 * 
 * MYSQLI_REPORT_ERROR: Report errors from mysqli function calls.
 * MYSQLI_REPORT_STRICT: Throw a mysqli_sql_exception for errors instead of warnings. 
 * 
 * @link http://php.net/manual/en/class.mysqli-driver.php
 * @link http://php.net/manual/en/mysqli-driver.report-mode.php
 * @link http://php.net/manual/en/mysqli.constants.php
 */
$mysqliDriver = new mysqli_driver();
$mysqliDriver->report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

/*
 * Create a new db connection.
 * 
 * @see http://php.net/manual/en/mysqli.construct.php
 */
$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE, PORT);

Create table syntax

CREATE TABLE `user_credentials` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

File system structure

includes
    connection.php
login.php
welcome.html

这篇关于如何使用php重定向到另一个html文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆