PHP实现增删改查以及防SQL注入

        最近项目调研时,需要在集成板子上做个配置的网页,板子上装的是linux系统,配置信息在一个SQLite数据库中,经过讨论大家决定用PHP做这个网页。由于项目组没一个会PHP的,所以安排我调研下写个Demo,经过几天的研究终于完成了Demo的调研(调研过程主要参考网络,具体开发就交给月底入职的小弟去做了,哈哈,有个小弟真好),特此记录(根据我调研的顺序展开)。

        项目截图:



        1.搭建环境

        首先当然是搭建环境了,我选择的是phpstudy(下载和安装可 参考,完全傻瓜式),编译器选择的是免费的Notepad++(只因为免费而选用,实际效果比记事本好点而已)。至此你可以开发第一个Hello World了。语法可 参考。发布也很简单,只要把php文件放到网站目录下就行了(如安装教程中,目录就是D:\WWW)。网站的端口号可以打开phpStudy主界面,点击其他选项菜单,点击myHomePage,就能看到端口号啦。

        2.PHP从SQLite中读取信息

        代码如下:

if ($db = sqlite_open('GateWay.db')) {
	$sql = "select * from ComInfo";
	$res = sqlite_unbuffered_query($db, $sql);

	echo "<table border=1><tr>";
	echo "<th>comId</th><th>comName</th><th>baud</th><th>parity</th><th>dataBit</th><th>stopBit</th>";
	echo"</tr>";
	while($item = sqlite_fetch_array($res, SQLITE_ASSOC))
	{
		echo "<tr>";
		echo "<td>".$item["comId"]."</td>";
		echo "<td>".$item["comName"]."</td>";
		echo "<td>".$item["baud"]."</td>";
		echo "<td>".$item["parity"]."</td>";
		echo "<td>".$item["dataBit"]."</td>";
		echo "<td>".$item["stopBit"]."</td></tr>";
	}
	echo "</table>";

	sqlite_close($db);
}

        3通过Ajax获得信息

        作为一个网站,现在很少能看到每次提交刷新整个页面的网站了。下面是通过Ajax请求获得数据(这个跟html中类似,这边用的是jQuery中封装的Ajax):在页面上有一个id为fullDataDiv的DIV用来装获取的数据,代码如下:
//js代码
var data={ opType:"ShowAllComInfo" };
$.post("ComInfoServer.php", data, function (result) {
	$("#fullDataDiv").html(result);
});


//ComInfoServer.php页面的代码
$opType = $_POST["opType"];
switch($opType)
{
	case "ShowAllComInfo":
	{		
		if ($db = sqlite_open('GateWay.db')) {
			$sql = "select * from ComInfo";
			$res = sqlite_unbuffered_query($db, $sql);

			echo "<table border=1><tr>";
			echo "<th>comId</th><th>comName</th><th>baud</th><th>parity</th><th>dataBit</th><th>stopBit</th>";
			echo"</tr>";
			while($item = sqlite_fetch_array($res, SQLITE_ASSOC))
			{
				echo "<tr>";
				echo "<td>".$item["comId"]."</td>";
				echo "<td>".$item["comName"]."</td>";
				echo "<td>".$item["baud"]."</td>";
				echo "<td>".$item["parity"]."</td>";
				echo "<td>".$item["dataBit"]."</td>";
				echo "<td>".$item["stopBit"]."</td></tr>";
			}
			echo "</table>";

			sqlite_close($db);
		} 
	}
	break;
}

        4.新建记录

        接着是新建记录,本质跟Ajax查询类似,代码如下:

//js代码
var comName = $('#tbComName').val();
var baud = $("select#selBaud option:selected").text();
var parity = $("select#selParity option:selected").text();
var dataBit = $("select#selDataBit option:selected").text();
var stopBit = $("select#selStopBit option:selected").text();
var data={opType:"AddComInfo",comName: comName, baud: baud,parity:parity,dataBit:dataBit,stopBit:stopBit};
$.post("ComInfoServer.php", data, function (result) {
	alert("Add Success!");
});


//ComInfoServer.php页面的代码
$comName =$_POST["comName"];
$baud = $_POST["baud"];
$parity = $_POST["parity"];
$dataBit = $_POST["dataBit"];
$stopBit = $_POST["stopBit"];

if ($db = sqlite_open($dbName)) {
	$sql= "insert into ComInfo values(null,'".$comName."', '".$baud."','".$parity."',  '".$dataBit."', '".$stopBit."')";	 
	sqlite_query($db, $sql);	

	sqlite_close($db);
} 

        5.删除记录

        然后就是删除记录,比新增还简单,只需要传一个ID就行,ID在当前行的第一列(var comInfoid = $(this).parents("tr").find('td:first').text();),代码跟新增类似,就不贴了。

        6.编辑记录

        最后是编辑,为了调研页面跳转,我把编辑放在另一个页面,页面传值直接放在url中,EditComInfoServer.php页面中放了一个隐藏控件保存ComInfoid的值,在页面加载完毕之后根据id向服务端请求完整的数据。代码如下:

//ComInfoMain.php的js代码
$(".edit").click(function(){
	var comInfoid = $(this).parents("tr").find('td:first').text();
	window.location= "ComInfoServer.php?ComInfoid="+comInfoid;
});


//EditComInfoServer.php
//隐藏控件
<div>
	<input type="hidden" id="tbComInfoid" value="<?php echo $_GET['ComInfoid']; ?>"/>
</div>
//js代码
$(function () {
	var URL = "ComInfoHandler.ashx";	
	var data={ComInfoid: $("#tbComInfoid").val(),opType:"EditInit" };
	$.post(URL, data, function (result) {
		var info=eval("(" + result + ")");
		comName =info.comName;
		baud = info.baud;
		parity = info.parity;
		dataBit = info.dataBit;
		stopBit = info.stopBit;
		$("#tbComName").val(comName);
		$("#selBaud  option[value='"+baud+"']").attr("selected", true);
		$("#selParity  option[value='"+parity+"']").attr("selected", true);
		$("#selDataBit  option[value='"+dataBit+"']").attr("selected", true);
		$("#selStopBit  option[value='"+stopBit+"']").attr("selected", true);
	});		
});

        7.PHP+Sqlite的防注入以及错误友好提示

        至此初步的增删改查都实现了,但只是实现,根本没考虑安全性。主要有三个方面:如果输入数据库的完整路径,数据库都被下载下来了;或者在comName里精心填入一些字符串就能实现SQL注入;另外出错了,提示也很不友好,直接把程序信息都泄露出来了。
        7.1防止数据库被下载
        对于数据库被下载(这个问题在Access和SQLite中都有),可以不让其直接访问,具体配置是在网站的根目录新建一个文件名为.htaccess的文件(直接新建不了,可以另存为该文件,另外注意的是这个文件与PHP的版本有关,我用的是Apache+PHP5.3),用记事本打开写入内容如下:

<FilesMatch ".db$">
	Deny from all
</FilesMatch>
        其他的设置在最新的版本中已经都是默认设置了,这样,数据库文件就不会被访问下载了。

        7.2防止SQL注入
        对于注入攻击,从两方面下手,前台验证输入的内容(过滤一些注入的关键字),后台再进行二次验证。根据我们实际的业务,我在前台只限制了长度,后台对传入的字符串进行加密之后存到数据库中的,读取的时候再解密。其中解密的几个方法 来自这里。这样做法其实对存储有浪费的,经过测试,加密后的字符串长度是原来的两到三倍,图省事我把comName的字段类型改成了text。在实际操作时还遇到了截取字符串乱码的问题,原因是substr在遇到汉字时会遇到编码问题,因此采用mb_substr方法。代码如下:

//新增或更新时
$postComName=$_POST["comName"];
if(strlen($postComName)>10)
{
	$postComName=mb_substr($postComName,0,10,'utf-8');
}
$comName =passport_encrypt($postComName,$key);
//读取时解密
$comName=passport_decrypt($item["comName"],$key);
        7.3URL重写
        在注入攻击的问题上还可以通过重写url隐藏网站的技术,当然这不能从本质上防SQL注入,只是提高注入的难度而已。在刚刚的.htaccess加入如下代码:

<IfModule mod_rewrite.c>
	RewriteEngine on
	RewriteRule main.html ComInfoMain.php
	RewriteRule ComInfoHandler.ashx ComInfoServer.php
	RewriteRule ^edit([0-9]+)\.html$ EditComInfoServer.php?ComInfoid=$1   
</IfModule>
        这样访问main.html就自动解析为ComInfoMain.php,其中第三个规则是用正则表达式实现,例如edit23.html就解析成EditComInfoServer.php?ComInfoid=23。这个调查了大半天,只因为网上的大多都是以讹传讹(或许是版本的原因吧)。当然了,还有一个原因就是配置文件的苛刻要求。在调查期间删除了一个"看似多余"空格导致Apache启动不起来了,元凶如下:

        这个空格删除了就启动不了Apache,而且没有什么有效的提示,真坑爹。

        7.4错误友好提示
        最后就是错误友好提示了,打开phpStudy主界面,点击其他选项菜单,点击打开配置文件选httpd.conf找到ErrorDocument 404,将其前面的#去除,在后面加上error的页面,本例中设置是ErrorDocument 404 /error.html,这里表示error.html放在网站根目录下。

        至此全部完成,Demo很简单,希望能对刚学PHP的读者有些帮助,欢迎阅读、讨论、转载,转载请保留原文链接

        Demo下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值