本文涉及到的点:
- 利用MySQLi或者PDO连接MySQL数据库
- 利用预处理SQL语句(Prepared SQL statements)防范SQL注入
- 利用htmlentities()防范Cross-Site Scripting (XSS)攻击
- 利用MD5对用户密码进行加密
- 利用HTTP headers防范Session Hijacking攻击
- W3C (HTML5 and CSS) Validation
PHP5 以后连接MySQL数据库有两种方式:
- MySQLi extension (MySQL extension在2012年就过时了)
- PDO
PDO支持12种数据库,MySQLi仅支持MySQL。所以如果你的项目有改变数据库的可能的话,无疑PDO是更好的选择。
安全方面,两种方式都支持Prepared SQL statements which can prevent your project from SQL injection.
首先将展现如何用PDO连接MySQL数据库:
// Creating a new PDO object
$pdo = new PDO(‘mysql:host=localhost; dbname=mydb’, ‘dbuser’, ‘dbpassword’);
?>
通常,为了安全起见,在实现与数据库连接的时候,连接需要的hostname, dbname, port, username, password等credentials信息需要单独封装在一个文件中并利用requrire_once()调用它们,比如:
// Database config
define('DB_HOST', 'dbhost');
define('DB_USER', 'dbuser');
define('DB_PASS', 'dbpassword');
define('DB_NAME', 'dbname');
?>
这样的话,当直接通过浏览器进入这个php页面的时候,浏览器只可能呈现空白。
同时,执行与数据库连接的代码也要单独封装起来,并且不要忘记使用try and catch来抓取PDOException,防止万一报错,错误信息泄漏在页面上的情况。举个例子:
try{
$pdo = new PDO(‘mysql:host=localhost; dbname=mydb’, ‘dbuser’, ‘dbpassword’);
//configure PDO error mode to catch exceptions and set character encoding
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('SET NAMES "utf8"');
}catch(PDOException $e)
//create a variable $output to contain info on what happened
//and include template output.html.php to output the value of $output.
$output = 'Unable to connect to the db server'.$e->getMessage();
include 'output.html.php';
exit();
}
?>
在不需要DB connection的时候,记得断开:
$pdo = null;
?>
接下来,如何用MySQLi连接MySQL。事实上,MySQLi有两种API:一种是面向对象的(same as PDO),另一种是procedural的。
利用MySQLi Procedural的例子:
$servername = "localhost";
$username = "username";
$password = "password";
// Create connection
$conn = mysqli_connect($servername, $username, $password);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
?>
断开连接:
mysqli_close($conn);
?>
利用MySQL Object-oriented的例子:
$servername = "localhost";
$username = "username";
$password = "password";
// Create connection
$conn = new mysqli($servername, $username, $password);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "Connected successfully";
?>
断开连接:
$conn->close();
?>
For more information, check out:
https://bramus.github.io/ws1-sws-course-materials/07.databases.summary.html
防范SQL注入是一个Web application必须要做到的。
假设我们在做一个登陆用的form,代码只是简单的写成这样:
$user = $_POST['user'];
$pass = $_POST['pass'];
$query = "SELECT * FROM user='$user' AND pass='$pass'";
?>
如果有人在输入username时输入admin’#,那他就能以admin的身份进入你的数据库并且不需要输入密码。这将是毁灭性的。
因此,为了防止这种情况的出现,我们需要使用Prepared SQL statements. 举例如下:
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
// 插入一行
$name = 'one';
$value = 1;
$stmt->execute();
// 用不同的值插入另一行
$name = 'two';
$value = 2;
$stmt->execute();
?>
另一个例子:
$sql = "INSERT INTO admin (username, password)VALUES(?, SHA1(?))";
$stmt = $db->prepare($sql);
$stmt->execute(array($_POST['username'], $_POST['password']));
?>
相比直接执行SQL语句,预处理SQL有以下三个优点:
- 解析时间减少,因为query的预处理(或者说解析)只需要执行一次,如果query的参数需要改变,只需要单独处理参数即可。
- 绑定的参数可以降低query送到server用的带宽。在执行不同的query时,无需再递送一次整个query,只需要改变参数,将参数送给server即可。
- 可以防范SQL注入,因为参数和query是分开发送给server的,参数是用不同的协议单独发送给server的,不需要转义。如果SQL语句的构成不包含外部输入的话,SQL注入也就不会发生。
For more information, check out:
https://websitebeaver.com/prepared-statements-in-php-mysqli-to-prevent-sql-injection
https://www.w3schools.com/php/php_mysql_prepared_statements.asp
http://php.net/manual/zh/pdo.prepared-statements.php
https://link.springer.com/content/pdf/10.1007/978-1-4302-2474-7.pdf
For more examples, check out:
http://php.net/manual/zh/mysqli.quickstart.prepared-statements.php
这篇博客还没有写完,只写了两个topic。最近实在太忙了,最近一定会抽空完成后续的!一学期四门课is driving me to death!!
本人还是个WEB开发领域的初级学习者,以上为本人在学习阶段习得的一点基本知识。如有不完整或有误的地方,还望各位大神不吝赐教,留下宝贵的意见。谢谢!
https://websitebeaver.com/prepared-statements-in-php-mysqli-to-prevent-sql-injection
https://bramus.github.io/ws1-sws-course-materials/07.databases.summary.html
https://www.w3schools.com/php/php_mysql_prepared_statements.asp
http://php.net/manual/zh/pdo.prepared-statements.php
https://link.springer.com/content/pdf/10.1007/978-1-4302-2474-7.pdf
http://php.net/manual/zh/mysqli.quickstart.prepared-statements.php
1