大多数 PHP 程序员对 MySQL 肯定不陌生,至于各种 MySQL 函数的用法在开发手册和 w3school 这类网站上也有很多介绍。但是,你所用的写法真的安全吗?面对越来越猖獗的黑客攻击,SQL 注入防范非常重要,所以使用 MySQL 也要有更正确的姿势。

关于 SQL 注入

SQL Injection:就是通过把 SQL 命令插入到 Web 表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令。

具体来说,它是利用现有应用程序,将(恶意)的 SQL 命令注入到后台数据库引擎执行的能力,它可以通过在 Web 表单中输入(恶意)SQL 语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行 SQL 语句。

在网上可以搜到一些简单例子,通过一步步有目的地调整 url 请求参数,让 server 返回其 MySQL 数据结构及内容,以达到获取敏感数据的目的。

防注入的方法

开发者要使用合适的数据库操作函数,这一点也是开发手册和教程上很少提到的。

举个例子,要实现一个简单的查询功能,一般会这样写:

<?php
$con = mysql_connect("localhost","mysql_user","mysql_pwd");
if (!$con)
{
die('Could not connect: ' . mysql_error());
} $username = $_POST['user'];
$password = $_POST['pwd']; $sql = "SELECT * FROM Person WHERE username=$username AND password=$password"; mysql_query($sql,$con); // 一些代码 mysql_close($con);
?>

这种用法相当不安全,如果被人盯上,会很容易地进行 sql 注入

所以有不少人推荐使用 mysql_real_escape_string,写法如下:

<?php
$con = mysql_connect("localhost","mysql_user","mysql_pwd");
if (!$con)
{
die('Could not connect: ' . mysql_error());
} $username = $_POST['user'];
$password = $_POST['pwd']; // 如果不是数字则加引号
$username = "'" . mysql_real_escape_string($username) . "'";
$password = "'" . mysql_real_escape_string($password) . "'"; $sql = "SELECT * FROM Person WHERE username=$username AND password=$password"; mysql_query($sql,$con); // 一些代码 mysql_close($con);
?>

这种方法安全性比第一种更高,但对方还是可以利用编码的漏洞来实现输入任意密码就能登录服务器的注入攻击。另外像一些 str_replace,addslashes 或者使用 magic_quotes_gpc 选项之类的方法,不是已经失效就是仍然有可能被破解。

然而百度一下「PHP 防注入」,仍然有很多文章在介绍上述办法。所以我们这里要郑重提示大家这个风险,提醒所有后来者绕过这个坑。

那么,如今还能幸免于注入的方法就是 Prepared Statement 机制了。这里推荐大家使用 mysqli 方式,mysql 扩展已经在 php5.5 中被废弃,在 php7 中更是直接不支持。为向高版本兼容考虑,新代码尽量使用 mysqli

最终的查询代码就变成了这样:

<?php
$mysqli=new mysqli("localhost","mysql_user","mysql_pwd"); if (mysqli_connect_errno())
{
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
} $username = $_POST['user'];
$password = $_POST['pwd']; if ($stmt = $mysqli->prepare("SELECT * FROM Person WHERE username=? AND password=?"))
{
$stmt->bind_param("ss",$username,$password); $stmt->execute();
} // 一些代码 $mysqli->close();
?>

把所有操作 MySQL 的代码都重构成上面这样,那么面对 SQL 注入就可以高枕无忧了。另外 pdo 也有 Prepared Statement 机制,同样能够保护数据库,有兴趣的同学可以自己尝试一下。

OneAPM for PHP 能够深入到所有 PHP 应用内部完成应用性能管理 能够深入到所有 PHP 应用内部完成应用性能管理和监控,包括代码级别性能问题的可见性、性能瓶颈的快速识别与追溯、真实用户体验监控、服务器监控和端到端的应用性能管理。想阅读更多技术文章,请访问 OneAPM 官方技术博客

本文转自 OneAPM 官方博客

PHP 如何安全的使用 MySQL ?的更多相关文章

  1. Hadoop 中利用 mapreduce 读写 mysql 数据

    Hadoop 中利用 mapreduce 读写 mysql 数据   有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...

  2. mysql每秒最多能插入多少条数据 ? 死磕性能压测

    前段时间搞优化,最后瓶颈发现都在数据库单点上. 问DBA,给我的写入答案是在1W(机械硬盘)左右. 联想起前几天infoQ上一篇文章说他们最好的硬件写入速度在2W后也无法提高(SSD硬盘) 但这东西感 ...

  3. LINUX篇,设置MYSQL远程访问实用版

    每次设置root和远程访问都容易出现问题, 总结了个通用方法, 关键在于实用 step1: # mysql -u root mysql mysql> Grant all privileges o ...

  4. nodejs进阶(6)—连接MySQL数据库

    1. 建库连库 连接MySQL数据库需要安装支持 npm install mysql 我们需要提前安装按mysql sever端 建一个数据库mydb1 mysql> CREATE DATABA ...

  5. MySQL高级知识- MySQL的架构介绍

    [TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而 ...

  6. 闰秒导致MySQL服务器的CPU sys过高

    今天,有个哥们碰到一个问题,他有一个从库,只要是启动MySQL,CPU使用率就非常高,其中sys占比也比较高,具体可见下图. 注意:他的生产环境是物理机,单个CPU,4个Core. 于是,他抓取了CP ...

  7. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  8. Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制

    将通用的序列号生成器库 从SQL Server迁移到Mysql 遇到的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Server数据库中的实现.SQ ...

  9. Docker笔记一:基于Docker容器构建并运行 nginx + php + mysql ( mariadb ) 服务环境

    首先为什么要自己编写Dockerfile来构建 nginx.php.mariadb这三个镜像呢?一是希望更深入了解Dockerfile的使用,也就能初步了解docker镜像是如何被构建的:二是希望将来 ...

  10. 当忘记mysql数据库密码时如何进行修改

    因为长时间没有使用数据库了,或者把密码改完之后就忘了数据库密码,不能正常进入数据库,也无法修改密码,有一个简单的常用修改密码方式: 1.首先找到和打开mysql.exe和mysqld.exe所在的文件 ...

随机推荐

  1. 30种mysql优化sql语句查询的方法<转>

    转自百度文库 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.   2.应尽量避免在 where 子句中使用!=或<>操作符,否 ...

  2. sql查询最大id

    如 有个表里有字段 id,name,..... 当name是重复时取其id最大的一条记录 select max(id) id,name from 表 group by name --最小用mini - ...

  3. 【原创教程】鲸吞HTML

    首先,我们的angularJS课程分为三大模块: HTML/CSS/JS基础. angularJS详解. angualrJS的一些实用框架讲解. 其中,第一大模块的对象是对前端开发技术有点了解但不熟悉 ...

  4. 19个非常有用的Javascript类库

    Blackbird是一款非常酷的JavaScript调试工具,带有一个漂亮的界面显示和过滤调试信息. http://www.gscottolson.com/blackbirdjs/ Treesaver ...

  5. Java对数组对象进行排序

    下面是一组对数组对象进行排序的代码: package com.sun; import java.util.ArrayList; import java.util.Arrays; import java ...

  6. java csv - 读写及其操作.

    今天帮同学处理数据, 主要是从1w多条记录中随机获取8k条, 然后再从8k条记录中随机获取2k条记录. 最后将2k条记录中随机分成10组,使得每组的记录都不重复. 下面将我的代码都贴上来, 好以后处理 ...

  7. Oracle中的rownum,ROWID的 用法

    1.ROWNUM的使用——TOP-N分析 使用SELECT语句返回的结果集,若希望按特定条件查询前N条记录,可以使用伪列ROWNUM. ROWNUM是对结果集加的一个伪列,即先查到结果集之后再加上去的 ...

  8. shell脚本学习之$0,$?,$!等的特殊用法

    变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行的命令的结束代码(返回值) $- 使用Set命令设定的Flag一览 ...

  9. 修改PYTHONPATH的一种方法(在Window平台和Ubuntu下都有效)

    1.显示PYTHONPATH 2.修改PYTHONPATH 通过PYTHONPATH 中的任何 .pth 文件来添加pythonpath.比如我想添加/home/aa这个路径到pythonpath里, ...

  10. 【POJ1707】【伯努利数】Sum of powers

    Description A young schoolboy would like to calculate the sum for some fixed natural k and different ...