PHP / MySQL用户认证

Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to use!  What is deprecated? Well in english it means "to strongly disapprove of." In software, features become deprecated because new features supersede them. The reason for deprecation instead of removal is to provide backwards compatability so programmers can update their code (which doesn't mean it happens!) although deprecated function may be removed completely in future version. So we must learn to cease and desist the use of deprecated functions.

所有技能水平的开发人员在开发网站时都应学习使用最新的最佳做法。 但是,许多新老开发人员都陷入使用过时功能的陷阱,因为这就是许多教程和书籍告诉他们使用的功能! 不推荐使用什么? 用英语讲,这意味着“强烈反对”。 在软件中,不赞成使用功能,因为新功能会取代它们。 弃用而不是删除的原因是为了提供向后兼容性,以便程序员可以更新其代码(这并不意味着它会发生!),尽管在以后的版本中可能会完全删除不赞成使用的功能。 因此,我们必须学会停止和停止使用不赞成使用的功能。

Keeping in mind that so many tutorials and books sport deprecated functions and classes, this tutorial is aimed at the beginner and intermediate user alike. The purpose of this tutorial is to teach you to create a basic user authentication system without relying on deprecated functions, or losing security. I find it absolutely boggling how many horrible tutorials are out there, and their impact is seen on a daily basis on forums all over. The main points that I think make this tutorial better than the other is that its written procedurally (not daunting objects to learn to use), it uses the MySQLi extension (the i stands for improved), and it doesn't skip simple security that every script should use. Why learn old, discontinued functions, bad practice, and weird syntax when you can learn it right the first time!

请记住,太多的教程和书籍都使用了不推荐使用的功能和类,因此本教程针对的是初学者和中级用户。 本教程的目的是教您创建基本的用户身份验证系统,而不必依赖不推荐使用的功能或失去安全性。 我发现那里有多少可怕的教程简直令人难以置信,它们的影响每天都在整个论坛上看到。 我认为使本教程比其他教程更好的要点是,它是按程序编写的(不是令人畏缩的对象以供学习使用),它使用MySQL 扩展(i表示经过改进),并且不跳过简单的安全性。每个脚本都应该使用的。 当您第一次就可以正确学习时,为什么还要学习旧的,停产的函数,不好的做法和奇怪的语法!

A few notes ahead of time; code snippets are incomplete on their own, to obtain the final files (with ample commenting througout) download the attached zip. Links to all the functions used in this code are provided at the bottom of the tutorial. If you don't understand how or why I used a function, my experience has taught me that the manual is by far the best place to start, and rather intuitive to use: just type in php.net/ followed by the function name (or close) that you are looking for; For example: php.net/echo which brings you to the manual page for the echo language construct. And last but not least, this tutorial assumes enough familiarity with either phpMyAdmin, MySQL Workbench, or the MySQL console to connect to your database.

提前注意一些事项; 代码片段本身并不完整,要获取最终文件(带有足够的注释输出),请下载附件的zip。 本教程底部提供了此代码中使用的所有功能的链接。 如果您不了解我如何或为什么使用函数,我的经验告诉我,该手册是迄今为止最好的入门指南,并且使用起来非常直观:只需输入php.net/,然后输入函数名(或关闭)您正在寻找; 例如: php.net/echo ,它将带您进入回显语言构造的手册页。 最后但并非最不重要的一点是,本教程假定您对phpMyAdminMySQL WorkbenchMySQL控制台足够熟悉,可以连接到您的数据库。

设置:步骤1-创建用户表 (Set-Up: Step 1 -  Create The User Table)

因此,让我们从创建一个非常简单的用户表开始。 为此,您需要使用MySQL Workbench,phpMyAdmin或MySQL控制台之类的工具连接到mysql。

In phpMyAdmin - select the database, click the SQL tab and copy paste the query into the box then click go.

在phpMyAdmin中-选择数据库,单击SQL选项卡,然后将查询复制粘贴到框中,然后单击执行。

In MySQL Workbench, connect to the server, select your database (you may have to right click the db and select "Set as default schema" to get it to work), copy paste the query into main entry spot in the middle of the window.

在MySQL Workbench中,连接到服务器,选择数据库(您可能需要右键单击db并选择“设置为默认模式”以使其正常工作),然后将查询复制粘贴到窗口中间的主入口处。 。



In the console you would type use DATABASE; where DATABASE is the name of your database. Then hit enter, then type in the query and hit enter again.

在控制台中,您将键入use DATABASE。 其中,DATABASE是数据库的名称。 然后按Enter键,然后键入查询并再次按Enter键。

CREATE TABLE IF NOT EXISTS `users` (
   `id` INT unsigned NOT NULL AUTO_INCREMENT,
   `username` varchar(20) NOT NULL,
   `email` varchar(75) NOT NULL,
   `password` char(64) NOT NULL,
   PRIMARY KEY (`id`),
   UNIQUE(`username`),
   UNIQUE(`email`)
) Engine=MyISAM;

设置:步骤2-适用于PHPMySQL登录凭据 (Set-Up: Step 2 - MySQL Log In Credentials for PHP)

现在我们有了表,我们需要存储我们MySQL凭据,以便PHP可以从PHP内部连接到服务器。 在这里,我们使用 define to create constants because our login credentials won't change during the execution of the script, and because they will then be available in any scope. For more information about scope see define来创建常量,因为在脚本执行期间我们的登录凭据不会更改,并且因为它们随后将在任何范围内可用。 有关范围的更多信息,请参见 Variable Scope. We also put this definition in its own file, instead of in each script so as to make it easier to update credentials if need be. We will just include this file in any file that needs to connect to MySQL. Variable Scope 。 我们还将此定义放在自己的文件中,而不是放在每个脚本中,以便在需要时更轻松地更新凭据。 我们只会将此文件包含在需要连接到MySQL的任何文件中。
<?php //mysql_info.php

define(  'DBHOST',   'localhost');
define(  'DBUSER',   'derokorian');
define(  'DBPASS',   'derokorian');
define(  'DBNAME',   'derokorian'); ?>

注册:步骤1-创建骨架脚本 (Registration: Step 1 - Create Skeleton Script)

现在我们可以开始构建第一个脚本:注册系统; 因为如果人们无法注册,那么他们将没有登录帐户! 我们将首先考虑要使它起作用需要发生什么。 好吧,我们需要一个供用户填写的表单,我们需要检查表单是否已提交,我们需要验证提交内容的准确性,我们需要将用户添加到数据库中,以及最后,我们需要能够处理所有错误并向用户报告。 现在可能暂时没有意义,但是该表单将与所有其他输出一起放在脚本的底部,但是我们首先将其创建,因此我们定义了表单字段。 因此,让我们开始制作一个框架脚本,其中包含我们知道需要做为注释的步骤:
<?php //userRegister.php
// Check if the form was submitted

// check that all fields are filled in

// check the validity of the entered data

// add user to the database

// show errors

// show form

注册:步骤2-创建表格 (Registration: Step 2 - Create the Form)

如您所见,尚无任何代码,但我们一次将其添加一次。 首先,让我们创建表单,稍后再添加更多内容,以使其更强大,但让我们从简单的内容入手。
// show form
?>
<!DOCTYPE html>
<html>
   <head>
      <title>Derokorian User Registration</title>
   </head>
   <body>
      <form action="" method="post">
         <label for="username">Username:</label><input type="text" name="username" value=""/><br />
         <label for="email">Email:</label><input type="text" name="email" value=""/><br />
         <label for="pass1">Password:</label><input type="password" name="pass1" /><br />
         <label for="pass2">Confirm Pass:</label><input type="password" name="pass2" /><br />
         <input type="submit" value="Register" />
      </form>
   </body>
</html>

注册:第3步-检查表单提交 (Registration: Step 3 - Check for Form Submission)

接下来,使用$ _POST数组上的 count on the $_POST array to check if it contains anything. We will move the comments of steps to take if the form was submitted to inside this block: count检查表单是否已提交,以检查表单是否包含任何内容。 如果将表单提交到此块中,我们将移动步骤注释。
// Check if the form was submitted
if( count($_POST) > 0 ) {
	// check that all fields are filled in

	// check the validity of the entered data
	
	// add user to the database
}

注册:步骤4-选中的必填字段 (Registration: Step 4 - Checked Required Fields)

接下来,我们将检查每个字段是否已填写。我们现在正试图查找丢失的字段,稍后将输出这些错误,因此,现在我们将创建一个空的$ errors数组,以向字段中添加错误消息是空的。 每个必填字段的处理过程都相同。 对于本教程,将需要所有字段。 我们检查该字段是否已提交并包含 empty : 数据:
// check that all fields are filled in, one at a time using empty()
if( empty($_POST['username']) ) {
	$errors[] = 'You must supply a username.';
}
if( empty($_POST['email']) ) {
	$errors[] = 'You must supply an email.';
}
if( empty($_POST['pass1']) ) {
	$errors[] = 'You must supply a password.';
}
if( empty($_POST['pass2']) ) {
	$errors[] = 'You must confirm your password.';
}

注册:步骤5-验证输入 (Registration: Step 5 - Validating Input)

因此,现在我们框架的下一步是检查用户输入内容的有效性,但是如果他们忘记输入内容,就没有必要检查用户输入内容,因此首先我们将使用count检查是否已经存在错误。 如果没有,那么我们检查字段。 我们将使用带有FILTER_VALIDATE_EMAIL选项的 filter_var with the FILTER_VALIDATE_EMAIL option. We will check the username to begin with a letter and contain only letters and numbers with a simple regular expression and filter_var检查电子邮件。 如果您不了解正则表达式,不用担心,我们将检查用户名是否以字母开头,并仅包含带有简单正则表达式和 preg_match if you don't understand regular expressions don't worry. And lastly we'll make sure that both passwords provided match using the == preg_match的字母和数字。 最后,我们将使用== comparison operator: 比较运算符确保提供的两个密码匹配:
// If there are not already errors from missing fields
if( count($errors) == 0 ) {
	// check the validity of the entered data
	// Check the username
	if( !preg_match('/^[a-z][a-z0-9]+$/i',$_POST['username']) ) {
		$errors[] = 'Your username must begin with a letter, and only contain letters and numbers.';
	}
	// Check the email
	if( !filter_var($_POST['email'],FILTER_VALIDATE_EMAIL) ) {
		$errors[] = 'You must supply a valid email.';
	}
	// Check the passwords
	if( $_POST['pass1'] != $_POST['pass2'] ) {
		$errors[] = 'You must supply matching passwords.';
	}
	
	// add user to the database
}

注册:步骤6-连接到数据库并准备插入数据 (Registration: Step 6 - Connect to DB and Prepare Data for Insertion)

接下来,我们需要准备要输入数据库的数据,但是,在继续之前,我们将再次检查是否存在错误。 我们现在需要使用 mysqli_connect now to be able to use mysqli_connect连接到MySQL,以便能够在用户名和电子邮件上使用 mysqli_real_escape_string on the username and email to prevent mysqli_real_escape_string来防止 SQL Injection. After trying to connect we will need to check if it connected successfully if not give a fatal error. Finally we will use one way hashing on the password make it harder for a hacker to get the user's password, should that hacker gain access to our database (and to protect the user from us knowing the password). To hash the password we will use SQL注入 。 尝试连接后,如果没有出现致命错误,我们将需要检查它是否成功连接。 最后,我们将使用一种对密码进行散列的方式,使黑客更难获得用户的密码,前提是该黑客获得了对我们数据库的访问权限(并防止用户知道我们的密码)。 为了对密码进行哈希处理,我们将 hash with the SHA256 algorith, and we will do what is called salting by concatenating the username to the password (after we make the username all lowercase, so its not case dependant). 哈希与SHA256算法结合使用,然后将用户名与密码连接起来(在将用户名全部设为小写,因此不依赖大小写之后),将其称为盐化。
// Check for errors in validity
if( count($errors) == 0 ) {
	// connect to mysql
	include 'mysql_info.php';
	$conn = mysqli_connect(DBHOST,DBUSER,DBPASS,DBNAME);
	
	// Check if the connection failed
	if( !$conn ) {
		//connection failed
		die('Failed to connect '.mysqli_connect_error());
	}
	
	// prepare data for database
	$username = mysqli_real_escape_string($conn,$_POST['username']);
	$email = mysqli_real_escape_string($conn,$_POST['email']);
	$pass = hash('sha256',strtolower($_POST['username']).$_POST['pass1']);
}

注册:步骤7-创建和执行查询 (Registration: Step 7 - Creating and Executing the Query)

Now our data is ready to go into the database! Lets try to insert it now, remember we must always check if the query was successful. Here I use die on success because the user won't need the form any longer, I added a link in the output of die to the login page however. If the query failed, we return the error code and error message that MySQL gave php using mysqli_errno and mysqli_error, respectively. Note that our table will reject a username and email that have already registered; though we aren't handling this problem in our current script as its beyond the scope of the tutorial. The error from MySQL that we output will show that the username and/or email is already registered, but this should be handled more gracefully in your application.

现在我们的数据已准备好进入数据库! 现在让我们尝试将其插入, 请记住我们必须始终检查查询是否成功。 这里我成功使用了die,因为用户不再需要该表单,但是我在die输出中向登录页面添加了一个链接。 如果查询失败,我们将分别使用mysqli_errnomysqli_error返回MySQL给php的错误代码和错误消息。 请注意,我们的表格将拒绝已注册的用户名和电子邮件; 尽管我们不在当前脚本中处理此问题,因为它超出了本教程的范围。 我们输出的来自MySQL的错误将显示用户名和/或电子邮件已被注册,但是应该在您的应用程序中更合理地处理它。

// Create the insert query
$sql = sprintf("INSERT INTO `users` (`username`,`email`,`password`) VALUES ('%s','%s','%s')",
		$username,$email,$pass);

// Attempt insert the new user
if( mysqli_query($conn,$query) ) {
	die('You have successfully registered as '.$_POST['username'].'<br /><a href="/userLogin.php">Click here</a> to log in.');
} else {
	// Insert failed, set error message
	$errors[] = 'Error adding user to database, MySQL said:<br>
		('.mysqli_errno($conn).') '.mysqli_error($conn).'</span>';
}

注册:步骤8-更新表格以显示错误和/或先前提交的输入 (Registration: Step 8 - Update Form to Display Errors and/or Previously Submitted Input)

最后,我们需要更新表单,以显示先前提交的数据(如果存在)以及$ errors数组中包含的错误(如果存在)。 我们将使用 isset to check if a value was previously submitted, then we use isset检查先前是否提交过一个值,然后使用 isset and issetcount to check if errors exist. If any errors exist, we put them inside a span that changes the text color to red, and then count检查是否存在错误。 如果存在任何错误,我们将其放在一个跨度中,该跨度会将文本颜色更改为红色,然后使用<br>粘合将所有错误内 implode all the errors using <br> as glue so they each appear on their own line: ,使它们分别出现在自己的行上:
//output the form
?>
<!DOCTYPE html>
<html>
   <head>
      <title>Derokorian User Registration</title>
   </head>
   <body>
      <?php echo isset($errors) && count($errors) > 0 ? '<span style="color:red">'.implode('<br>',$errors).'</span><br>' : ''; ?>
      <form action="" method="post">
         <label for="username">Username:</label><input type="text" name="username" value="<?php echo isset($_POST['username']) ? $_POST['username'] : ''; ?>"/><br>
         <label for="email">Email:</label><input type="text" name="email" value="<?php echo isset($_POST['email']) ? $_POST['email'] : ''; ?>"/><br>
         <label for="pass1">Password:</label><input type="password" name="pass1" /><br>
         <label for="pass2">Confirm Pass:</label><input type="password" name="pass2" /><br>
         <input type="submit" value="Register" />
      </form>
   </body>
</html>

That's it our user registration is complete! (Don't forget the full version, properly nested, formatted, and commented is in the zip at the end of this tutorial).

就是这样,我们的用户注册完成! (不要忘记完整的版本,正确嵌套,格式化和注释的内容位于本教程末尾的zip中)。

身份验证:步骤1-创建骨架脚本 (Authentication: Step 1 - Create Skeleton Script)

现在,我们需要开始处理我们的登录脚本。 我们将使用一个 session to track if a user is logged in so and we will need to check if they are already logged in. Next we will need to create a form, check if the form was submitted, check that requried fields are filled in, check the username / password combination against the database, keep track of errors a long the way, and return feedback about successful / failed log in. We will start with a skeleton script again: 会话来跟踪用户是否已登录,因此我们将需要检查他们是否已经登录。接下来,我们将需要创建一个表单,检查该表单是否已提交,检查是否需要填写字段填写,针对数据库检查用户名/密码组合,长期跟踪错误,并返回有关成功/失败登录的反馈。我们将再次从框架脚本开始:
<?php //userLogin.php
// Start the session

// check if the user is logged in

// check if the form was submitted

// verify fields are filled in

// check the given username / password against the database

// tell the user they are logged in, if they are

// tell them why they aren't logged in, if they tried, and show the form

身份验证:步骤2-启动会话并检查登录 (Authentication: Step 2 - Start Session and Check for Login)

让我们从我们刚开始的前2个评论步骤开始。 我们将调用 session_start to get a session ID ( session_start来获取一个会话ID( Note: session_start MUST be called before any output, including (but not limited to) whitespace outside of php tags.) then we will use isset to check if the user is logged in: isset来检查用户是否登录:
// Start the session
session_start();

// check if the user is logged in
if( isset($_SESSION['username']) ) {
	die('You are already logged in');
}

身份验证:步骤3-创建表单 (Authentication: Step 3 - Create the Form)

现在,我们将创建表单。 这是一个非常简单的形式,只有两个输入字段。
// Output the form
?>
<!DOCTYPE html>
<html>
   <head>
      <title>Derokorian User Login</title>
   </head>
   <body>
      <form action="" method="post">
         <label for="username">Username:</label><input type="text" name="username" value=""/><br>
         <label for="password">Password:</label><input type="password" name="password" /><br>
         <input type="submit" value="Log in" />
      </form>
   </body>
</html>

身份验证:步骤4-检查表单提交 (Authentication: Step 4 - Check for Form Submission)

同样,我们将使用 count to check if the form was already submitted: count来检查表单是否已经提交:
// check if the form was submitted
if( count($_POST) > 0 ) {
	// verify fields are filled in

	// check the given username / password against the database
	
	// tell the user they are logged in, if they are
}

身份验证:步骤5-检查必填字段并准备数据以进行查询 (Authentication: Step 5 - Check Required Fields and Prepare Data for Query)

接下来,我们将检查字段是否已填写,并为数据库准备数据。 我们会再次做到这一点使用 empty to check if fields are filled in, connecting to mysql with ,以检查是否字段填写,连接到MySQL与 mysqli_connect, showing connection errors with mysqli_connect ,显示连接错误与 mysqli_connect_error and using mysqli_connect_error和使用 mysqli_real_escape_string to prepare the username, and using mysqli_real_escape_string准备的用户名,并使用 hash to encode the password with lowercase username. Finally using 散列编码与小写的用户名密码。 最后再次使用 count again to check if there are errors along the way: count来检查过程中是否存在错误:
// verify fields are filled in
$errors = array();
if( empty($_POST['username']) ) {
	$errors[] = 'You must enter a username.';
}
if( empty($_POST['password']) ) {
	$errors[] = 'You must enter your password.';
}

if( count($errors) == 0 ) {
	// Connect to mysql
	include 'mysql_info.php';
	$conn = mysqli_connect(DBHOST,DBUSER,DBPASS,DBNAME);
	
	// Check if the connection failed
	if( !$conn ) {
		//connection failed
		die('Failed to connect '.mysqli_connect_error());
	}
	
	// prepare data for database
	$username = mysqli_real_escape_string($conn,$_POST['username']);
	$pass = hash('sha256',strtolower($_POST['username']).$_POST['password']);
}

身份验证:步骤6-创建和执行查询 (Authentication: Step 6 - Create and Execute Query)

现在,我们必须构建查询以检查数据库,如果找到用户名/密码组合,则它们具有正确的登录凭据,我们需要将该信息添加到$ _SESSION数组中。 如果不是,我们需要告诉他们他们的用户名/密码组合不匹配。
// Build the query
$sql = sprintf("SELECT 1 FROM `users` WHERE `username` = '%s' AND `password` = '%s'",$username,$pass);

// check the given username / password against the database
$res = mysqli_query($conn,$sql);

// Check if the query was successful
if( !$res ) {
	$errors[] = 'Error selecting user from database, MySQL said:<br>
         ('.mysqli_errno($conn).') '.mysqli_error($conn);
} else {
	// Check if the result returned a row
	if( mysqli_num_rows($res) > 1 ) {
		// Successfully logged in
		$_SESSION['username'] = $_POST['username'];
		die('You have successfully logged in.');
	} else {
		// Username/password mismatch
		$errors[] = 'Your username and password combination wasn\'t found. Please try again.';
	}
}

身份验证:步骤7-更新表单以显示错误和/或以前提交的输入 (Authentication: Step 7 - Update Form to Display Errors and/or Previously Submitted Input)

登录脚本的最后一步是创建表单,输出错误,并在表单已发布的情况下为用户名提供默认值。 这与注册表格的过程相同。
// Output the form
?>
<!DOCTYPE html>
<html>
   <head>
      <title>Derokorian User Login</title>
   </head>
   <body>
      <?php echo isset($errors) && count($errors) > 0 ? '<span style="color:red">'.implode('<br>',$errors).'</span><br>' : ''; ?>
      <form action="" method="post">
         <label for="username">Username:</label><input type="text" name="username" value="<?php echo isset($_POST['username']) ? $_POST['username'] : ''; ?>"/><br>
         <label for="password">Password:</label><input type="password" name="password" /><br>
         <input type="submit" value="Log in" />
      </form>
   </body>
</html>

That's it for our user log in script! (Don't forget the full version, properly nested, formatted, and commented is in the zip at the end of this tutorial).

我们的用户登录脚本就是这样! (不要忘记完整的版本,正确嵌套,格式化和注释的内容位于本教程末尾的zip中)。

身份验证:注销 (Authentication: Logging Out)

最后但并非最不重要的一种注销方法是必需的,这就像调用call session_destroy. session_destroy一样简单。
<?php //userLogout.php

session_destroy();
echo 'You have been logged out.';

?>

That's it! Hopefully now you understand the process of registering and authenticating users better and that you have the tools and knowledge to do it properly!

而已! 希望现在您能更好地了解用户注册和身份验证的过程,并拥有适当的工具和知识!

外部链接 (External Links)

手册页: http://php.net/define http://php.net/define http://php.net/isset http://php.net/isset http://php.net/empty http://php.net/empty http://php.net/count http://php.net/count http://php.net/implode http://php.net/implode http://php.net/filter_var http://php.net/filter_var http://php.net/operators.comparison http://php.net/operators.comparison http://php.net/sprintf http://php.net/sprintf http://php.net/hash http://php.net/hash http://php.net/strtolower http://php.net/strtolower http://php.net/session_start http://php.net/session_start http://php.net/session_destroy http://php.net/session_destroy

MYSQLI PAGES

MYSQLI页面

http://php.net/mysqli_connect http://php.net/mysqli_connect http://php.net/mysqli_connect_error http://php.net/mysqli_connect_error http://php.net/mysqli_real_escape_string http://php.net/mysqli_real_escape_string http://php.net/mysqli_query http://php.net/mysqli_query http://php.net/mysqli_errno http://php.net/mysqli_errno http://php.net/mysqli_error http://php.net/mysqli_error userLogin.php userLogin.php mysql-info.php mysql-info.php CreateTable-Users.sql CreateTable-Users.sql userRegister.php userRegister.php PHP-MySQL-User-Authentication.zip PHP-MySQL-User-Authentication.zip

翻译自: https://www.experts-exchange.com/articles/9739/PHP-MySQL-User-Authentication.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值