今天我说一下怎么在框架中over掉这些安全问题。 php
首先是SQL注入,这个若是你使用的是PDO,我以为应该没什么问题,若是你使用的仍是mysql_*等API,那么你能够在框架中实现bindParameter或者在插入数据库以前进行字符串转义。 mysql
前两天把上一篇文章写完以后,Vian在后面留言说到过SQL注入的一个解决方案,就是在在插入DB以前进行'''.addslashes($id).''',它的意思就是首先进行addslashes操做,以后再强制单引号包裹,这样它就是一个彻彻底底的字符串了,因此就注入不了,我以为这个方法不错,赞一个!! 程序员
因为SQL注入须要联系到模型,XSS须要联系到视图,这两块儿我都没有开始讲,因此我再后面再讲怎么在框架中解决,固然,若是我写到后面忘记了,你也能够提醒我一下。 sql
上一次我讲CSRF的时候,并无给出一个解决方案,今天我就给出这个解决方案。实际上解决的方法很简单,就是给它产生一个随机数,而后后端断定传递过来的数和正确的数是否吻合, 若是不吻合,就不执行相应的代码了,这个随机数咱们称为token。 数据库
为了简单,咱们就将产生token和获得token的函数都写在控制器中,即Controller.php。 后端
首先是生成随机数,最简单的方式是使用mt_rand()直接产生一个整数,但在这儿我使用以前我在initphp这个框架中看到的解决csrf的方法,在这儿,也谢谢initphp做者的思路: 安全
initphp的代码是: cookie
private function set_token() { if (!$_COOKIE['init_token']) { $str = substr(md5(time(). $this->get_useragent()), 5, 8); setcookie("init_token", $str, NULL, '/'); $_COOKIE['init_token'] = $str; } }为了简单,我这儿就不使用userAgent了,initphp是将当前时间戳和userAgent拼接成字符串以后再md5加密,取出第5到8位,我这边的思路是将当前时间戳进行md5加密,而后从第0位开始取,取得的字符串长度是随机产生的:
$token = substr(md5(time()),0,mt_rand(10,15));为了防止随机数太大或过小,我设置mt_rand的取值范围为10到15,也就是说产生的token的位数为10到15位。
生成token以后其余的事情就好办了,固然,首先,也是设置token,咱们没有必要每次用户请求的时候都产生一个随机数,因此咱们将它存放在COOKIE中,框架载入的时候会断定是否有token,若是没有则动态生成一个,固然,生成的token会在一段时间以后过时失效,我这儿设置的时间为7天。 框架
private function _setToken() { if(empty($_COOKIE['_csrfToken'])) { $token = substr(md5(time()),0,mt_rand(10,15)); $this->_token = $token; setcookie('_csrfToken',$token,time() + 3600 * 24 * 7); } else { $this->_token = $_COOKIE['_csrfToken']; } }
因为生成token的过程是框架自动完成的,因此没有必要让用户看到此过程,因此将这个函数设为私有,而后在Controller类的构造函数中调用便可。 jsp
刚才是生成token,那么怎么获得token呢,实际上获得token的方法就很是简单了,就是一个简单的getter:
protected function _getToken() { return $this->_token; }如今我再演示一下在用户编写的控制器的断定过程:
假设用户请求的URL是:http://localhost/index.php?c=Index&a=test&token=rwerdfdsfsdfs
那么这个控制器的类的代码以下:
<?php class IndexController extends Controller { public function test() { $token = empty($_GET['token']) ? '' : $_GET['token']; if($token === $this->_getToken()) { //断定为正常 } else { $this->_redirect(array( //跳转到某一个控制器的某一个Action )); } } }可能有人会问URl上面的token值是怎么设置而后传递过来的呢?
咱们能够想一下,假设上一个页面是Index控制器的test2这个Action,那么咱们能够在test2这个Action中首先使用$this->_getToken获得token值,而后在将数据传递到视图,视图中使用了以后,用户点击这个连接就能够将这个token值传递过来了。
我如今提一个问题,假设用户访问A页面的时候获得token,这个token还有两秒就过时了,这个用户三秒以后点击这个含有token的连接到达B页面,B页面因为COOKIE中的token已经失效,因此从新产生一个token,而后再和传递的这个token比较,天然不匹配,而后就跳转了,这还不是有问题的呢,那么怎么解决呢?
因为还有一点时间,因此我提一下上传文件漏洞吧,用户上传一个好比test.php页面,若是用户没有作文件类型的断定,用户上传这个php文件以后,按照连接访问这个页面,有可能这个页面中有一些破坏性的代码,整个网站就危险了。
可能你已经在程序中断定了,只容许后缀为jpg,png,gif这三种类型,那么我能够将这个jsp页面后缀改为如jpg,上传成功以后,若是网站存在某种漏洞可以让它修改文件后缀,那么你的网站又危险了!!
还假设你的网站不容许修改文件后缀名,可是它在上传的图片后面加上一段JS脚本或者在上传的文件名上面写一些脚本,这些均可能很危险!!
因此,作好一个WEB应用不是想象中那么容易的,刚才说的是安全这一起的内容,实际上当访问量大了以后,以前你以为彻底不是问题的问题可能就变成了一个大的问题,除了这两个,还有其余N个问题,因此,保持低调,继续学习,继续提升。。。。
上面一段话仅以自勉,其余人能够忽略。
大四了,还有一个月就要离开天猫回学校作毕设了,我很想在毕业以前给个人网站作一个大幅度的修改,可是我如今不知道到底要作什么,不过确定这个网站是针对程序员的,但愿你们提一点意见,个人我的网站http://www.qingyueit.com(比较挫,很久都没有更新文章了,甚至连界面也是直接用了别人的主题)。
本次代码点此下载