PHP CodeIgniter学习笔记详解
(中文官网:http://www.bootcss.com)好的东西大家都喜欢,但是它对IE6-9的兼容几乎是0。大家也懂的,国外基本是不使用这几款浏览器了。不过在中国,IE依然占有很高的市场份额。所以,有人开发了一款叫做BSIE的Bootstrap插件,美其名曰鄙视IE,使用方法也相当简单。好像有点跑题,后端我用的是CodeIgniter,它是基于PHP的开源框架。CI是今天的正题。
因为CI对于数据的过滤函数只有xss_clean(),(不知道是不是自己才疏学浅,总之没有找到其他的过滤函数)而今天的项目涉及到接收用户数据,然后提交数据库的操作。没有针对SQL语句的过滤,使得这一操作变得很危险。有点蛋蛋的忧桑,我想到的方法是改写CI的xss_clean()函数,使之具备过滤SQL注入语句的功能;一来改起来方便,二来过滤数据的时候不用嵌套两个函数。说干就干,在CI/system/core/目录下找到secure.php文件,找到xss_clean()函数的申明位置,在最后加上这么一段东西。
PHP代码
代码如下 | 复制代码 |
$str = str_replace("_","x",$str); $str = str_replace("%","x",$str); $str = str_replace(""","x",$str); $str = str_replace("'","x",$str); $str = str_replace("select","x",$str); $str = str_replace("update","x",$str); $str = str_replace("insert","x",$str); $str = str_replace("set","x",$str); $str = str_replace("where","x",$str); $str = str_replace("from","x",$str); $str = str_replace("alert","x",$str); $str = str_replace("like","x",$str); return $str; |
这样差不多能避免一般的SQL注入了。
相信不少和我一样的php新人在学习PHP的时候和我一样,都郁闷过这个问题。@(at)这个记号到底是做什么的呢?
一次,下载别人的源码来看,看到无数@记号,开始以为是注释;后来发现@后面的语句也是会执行的。纳闷了,这个记号究竟是做什么的呢.....
随着学习的不断深入,总算是明白了。这个记号的作用有点类似于asp中的忽略错误"on error resume next "。他们的作用是一样的,当php解释器遇到@开头的语句时候,无论本行的语句是否执行成功,都会继续执行后续的语句,而且不会报错。但特别注意,@(at)记号只对当前行起作用哦。
希望关于@(at)的问题就在这打住把。
eg.下面这句话肯定报错
报错代码
代码如下 | 复制代码 |
<?php
|
然而,如果我们加上@(at)记号,就不会报错了,而且继续执行。
不报错代码
代码如下 | 复制代码 |
<?php |
继续执行下边的代码。
代码如下 | 复制代码 |
@$page=$_GET['page']?intval($_GET['page']):1; |
这句是从URL中获取page关键字的值,比如"index.php?page=5",则$page就会取到5。
但是如果有error,比如"index.php"后没有page关键字了,如果去取$_GET['page']不存在就会报错,这时有@就可以忽视这个小错误了。
又比如:
代码如下 | 复制代码 |
$conn = mysqli_conncet("q","w","e","r"); |
这样会输入错误信息,关于连接数据库方面的。
代码如下 | 复制代码 |
@$conn = mysqli_conncet("q","w","e","r"); |
如果$conn前面加@的话就可以不让他输出错误信息了。
又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来。
开始觉得这玩意很简单,结果嘛惨不忍睹。用CodeIgniter的上传类来上传文件,一开始进展蛮顺利的,但发觉走到上传文件类型的时候就走不下去了。我明明添加了.torrent类型为可上传类型,结果无论我怎么传也传不上去,还提示我上传文件类型不对。汗森了,这可是货真价实的种子文件啊,难道CI只认可岛国的种子吗?
打开CI的上传类看代码,原来CI的UPLOAD是通过判断文件的来实现文件识别的。难怪,种子的MIME类型在一般浏览器上返回的都是二进制数据类型,看来只有自己动手改造一下了。
为了尽快完成项目,我直接从控制器(Controller)开始写代码。用$_FILE['file']['name']获取上传文件的文件名,然后用explode函数来获取后缀名,最后再调用CI的UPLOAD来上传文件。代码如下:
PHP代码
代码如下 | 复制代码 |
$config['upload_path'] = './uploads/'; $config['allowed_types'] = '*'; $config['max_size'] = '100'; $this->load->library('upload',$config); $this->load->helper('security'); $this->load->helper('date'); $this->load->helper('url'); $this->load->model('bt_model','',TRUE); $data['source_url'] = base_url().'source'; $data['base_url'] = base_url(); $file = $_FILES['upload_file']['name']; $file_1 = explode('.',$file); $file_2 = $file_1[count($file_1)-1]; if($file_2 <> 'torrent'){ echo '<script>alert("只能上传类型为torrent的种子文件");</script>'; echo '<script>window.location.href="'.$data['base_url'].'index.php/index/post";</script>'; return; } $data['type'] = xss_clean($this->input->post('type')); $data['name'] = xss_clean($this->input->post('name')); $data['space'] = xss_clean($this->input->post('space')); $data['username'] = xss_clean($this->input->post('username')); $data['time'] = mdate('%Y-%m-%d %G:%i',gmt_to_local(time(),'UP8')); if($data['type'] == '' || $data['name'] == '' || $data['space'] == '' || $data['username'] == ''){ echo '<script>alert("信息填写不完整,请重新填写");</script>'; echo '<script>window.location.href="'.$data['base_url'].'index.php/index/post";</script>'; return; } $this->upload->do_upload('upload_file'); echo $this->upload->display_errors(); $file = $this->upload->data(); $data['url'] = $data['base_url'].'uploads/'.$file['file_name']; $this->bt_model->insert($data); echo '<script>alert("上传成功");</script>'; echo '<script>window.location.href="'.$data['base_url'].'";</script>'; |
原理大致是这样的,获取上传文件的文件名,然后通过explode()函数来分割文件名以获取后缀,得到后缀之后与允许上传类型做比较,最后上传。
讲到上传,我又想到了原来那个特别流行的MIME上传漏洞。很简单,当网站判断上传文件类型时只判断MIME类型那么就会造成上传漏洞。因为上传时服务器得到的MIME类型是从客户端发过来的,也就是说MIME类型的值是可以被用户控制的,攻击者克构造虚假的MIME类型来上传webshell。
所以判断文件类型的时候还是检测文件后缀名吧,最好只给上传目录一个可读权限,关闭执行权限,这样比较靠谱。
在php中cookie和session经常是配合使用的,但是cookie安全性没有session高了,session只在服务器端而cookie在客户端,这个自然就明白它们的区别了,但它们经常用于各种登录验证,下面我来介绍。Cookie和Session算是网站登陆验证的常用手段了。不管论坛也好,微博也好,它们都依赖于cookie和session以完成各项工作。
这里就不具体介绍Cookie和Session的概念了,我们可以简单的把它们理解为临时钥匙,用于开启不同的网络资源。
下面开始介绍在PHP里如何操作Cookie和Session。
Cookie:
在PHP里,我们可以使用setcookie()函数来设置cookie。但特别注意,setcookie函数必须置于<html>标签之前。setcookie函数包含了一下几个参数:setcookie(name, value, expire, path, domain)。name参数是用来规定cookie的名称的,而value则是规定对应名称cookie的值,expire则是设定cookie有效期的。特别注意path和domain参数可选的。(path是规定cookie的服务器路径,而domain是规定cookie的所有域名)。
一般我们这样设置cookie
设置cookie
代码如下 | 复制代码 |
<?php
|
username就是我们cookie的名字了,而Ku_Andrew则是username的值,time()+3600就是一小时后该cookie过期。
现在我们用$_COOKIE来做一个实例
设置、读取cookie
代码如下 | 复制代码 |
<?php
|
如果想做出更复杂的判断,例如用户登陆等,我们可以在IF语句中的加入从数据库从检索出来的值。
Session:
与Cookie不同,Session是保存在服务器上的,同时Session会随着浏览器的关闭而自动灭亡,生命周期较短。在PHP上,我们使用session_start()函数来启动session;与设置cookie相同,我们必须在<html>标签之前使用这个函数。使用这个函数之后我们就可以开始设置我们的Session变量了。方法也是极为简单:用$_SESSION数组直接定义。完成了定义,在不使用的时候为了节约服务器资源,我们要关闭它。这时可以使用unset()函数或者session_destroy()函数;unset()是解除变量,session_destroy()则是彻底终结session。下面是代码片段。
Session设置、读取
代码如下 | 复制代码 |
<?php |
这是一个简单的网页计数器,通过设置pid来实现计数。第一次判断中,如果session为空,那么设置成一,并且读取session,反馈给用户。以后的每次访问,都会在原有session的基础上逐次加一反馈给用户。
果文章出现错误,希望各位包涵、指出。
言归正传,对于PHP来讲,它是默认支持MYSQL的,也就是说我们不必再去手动设置ODBC来使用MYSQL了,我们所需要做的设置就是在php.ini中引入MYSQL插件。首先找到你的php.ini,编辑它,将extension = php_mysql.dll前的分号(“;”)去掉即可。这样,我们的php就可以使用MYSQL了。
接下来我们连接mysql,mysql_connect(servername:port,username,password)就是用于连接mysql的函数,其中servername:port参数就是数据库地址以及数据库端口(默认情况下port参数为3306);username即是登陆数据库所使用的用户名,password则是对应用户的密码。由于我的数据库就在本机上所以连接时我使用以下语句。
连接代码
$con = mysql_connect("localhost","root",""); //$con可理解为连接号
当然我们不能让mysql一直处于连接状态,对于小型应用来说或许这不算问题,但对于大型web应用来讲这是很浪费资源的,所以用完数据库连接之后我们要关掉它。这个任务我们交给mysql_close(连接号)来完成。
开启和关闭数据库连接
代码如下 | 复制代码 |
$con = mysql_connect("loaclhost","root",""); $con = mysql_close($con); |
弄明白了如何连接和断开数据库,接下来就是在mysql中创建数据库,这听起来很拗口,因为同一台mysql服务器中可以允许多个数据库的存在。这里我们有两种方法来建立数据库,法一使用mysql_create_db()函数,但不建议大家使用这种方法。
创建数据库
代码如下 | 复制代码 |
$con = mysql_connect("localhost","root",""); |
法二,我们直接采用mysql_query()函数来执行sql语句。Create DATABASE 就是用于创建数据库的sql语句,例如Create DATABASE test,就是创建一个名为test的数据库。
创建数据库
代码如下 | 复制代码 |
$con = mysql_connect("localhost","root","");
|
建完数据库,我们要向数据库中添加数据表。同样是采用mysql_query()函数来执行sql语句,但不同的是之前我们要使用mysql_select_db()函数来选择我们操作的数据库。
代码如下 | 复制代码 |
$con = mysql_connect("localhost","root",""); mysql_query("Create DATABASE guestbook",$con); mysql_select_db("guestbook",$con); mysql_query("Create TABLE users(username varchar(15), password varchar(15))"); mysql_close($con); /* 建表语句: Create TABLE 表明(字段名_1 字段数据类型_1,字段名_2 字段数据类型_2,......,字段名_n 字段数据类型_n) */ |
在数据库中建立好表、字段等数据数据关系之后,就差实实在在的数据了。同上,使用mysql_query()函数执行添加数据的sql语句,Insert INTO 表名 (字段名_1,字段名_2,......,字段名_n) VALUES (数据_1,数据_2,......,数据_n)。
代码如下 | 复制代码 |
|
现在,我们的数据库中已经有了数据,接下来我们使用select语句来进去查询。
代码如下 | 复制代码 |
$con = mysql_connect("localhost","root",""); mysql_query("Create DATABASE guestbook",$con); mysql_select_db("guestbook",$con); mysql_query("Create TABLE users(username varchar(15), password varchar(15))"); $select = mysql_query("select * from users"); while ($row = mysql_fetch_array($select);) { echo $row['username']; echo $row['password']; } mysql_close($con); |
这样,通过while循环我们就可以把users表中所有的数据全部查询出来,上面这样做不好重复利了,下面我们可以做成数据库连接类。
代码如下 | 复制代码 |
<?php class Database { function Database($dbHost = SERVER, $dbUser = USER, $userPassword = PASSWORD, $database = DATABASE) { /* SQL:Select() 返回为false无结果 */ function Select($table, $columns, $condition = 1) { /* SQL:GetRows() 返回查询的记录总数 */ function GetRows($table, $condition = 1) { /* SQL:Insert() */ function Insert($table, $columns, $values) { /* SQL:Update() */ function Update($table, $setings, $condition) { /* SQL:Delete */ function Delete($table, $condition) { /* Halt():error message */ function Halt($msg) { switch ($db->dbType) { |
相关文章
- 我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
- 1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
- 当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
- 举一个简单的date例子 我将使用echo命令把内容输出到我们的客户端(浏览器)。我将使用下面的代码做为基础代码。 代码如下 复制代码 <!DOCTY...2016-11-25
- 一篇Android学习笔记之多界面切换实例,希望对各位朋友有所帮助。 用过VB 、 VC#的朋友都知道,在VB或VC#里要进行窗口(界面)切换很容易 例如在VB、C#里: 有 Fom1、...2016-09-20
- 引用:意思是将原始对象在内存中的地址传递给目标对象,就相当于原始对象和目标对象指向的是同一个内存地址。此时,如果对目标对象或者原始对象进行修改,内存中的数据也会改...2016-11-25
- cURL是php中一个很强大的功能,可以模仿各种用户请求,如模仿用户登录,发送php cookie等等操作,下面我来整理一些相关的方法与各位同学看看 备注:使用curl_init函数,必须...2016-11-25
- 那些年学了ASP.NET后,才开始学习C#,说来也怪,怎么学了ASP.NET才来学习C#,其实没有什么的...2020-06-25
- CWidget是所有Widget的基类。CWidget是自包含组件,可以看出是MVC的简略版,CWidget相比Controller,既没有actions,也没有filters widget,英文意思为小工具,小挂件,在程序...2016-11-25
- Metasploit是一个免费的、可下载的框架,通过它可以很容易地获取、开发并对计算机软件漏洞实施攻击。它本身附带数百个已知软件漏洞的专业级漏洞攻击工具 nexpose安...2016-11-25
- PHP扩展开发不是所有开发者都会操作的一个东西,下面我来演示一个关于PHP扩展开发实现过程,各位同学有需要可进入参考。 我们先假设需要这样一个扩展,提供一个叫tao_s...2016-11-25
- 小编推荐的这篇文章介绍了Yii2学习笔记之汉化yii设置表单的描述,非常实用,有兴趣的同学快来看看吧。 一:汉化框架  框架汉化在这里设置,如果不生效,前台后...2017-07-06
- 星际里面有不少的任务关,也可以自己编辑地图,画面上有各种地形,建筑和部队,存在一个问题,初始化画面的流程很乱。待解决的问题:完成初始化画面的工作,同时尽量减少各种绘制...2016-11-25
- Session指的就是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。从上述的定义中我们可以看到,Session实际上是一个...2016-11-25
- 单例模式是php中一个为了简化大家开发及重复调用的一个功能,下面我来给各位朋友详细介绍单例模式用法。 1.单例模式的概念 顾名思义,单例模式只有一个实例,而且自行...2016-11-25
- 这篇文章主要介绍了CI(CodeIgniter)模型用法,结合实例形式分析了CodeIgniter框架中模型的功能、使用方法与相关注意事项,需要的朋友可以参考下...2016-01-23
- 本文章给大家分享一篇php正则表达式子模式的反向引用学习笔记,希望此教程对各位朋友有帮助哦。 需要用正则表达式获取字符串的标题。标题标签是h1~h6。 使用正则...2016-11-25
- 这篇文章主要介绍了jqGrid 学习笔记整理——进阶篇(一 )的相关资料,需要的朋友可以参考下...2016-04-19
- 适配器模式许多和php程序员都没有碰到关于适配器的应用了,这里小编整理了两个关于适配器的使用例子,下面我们就一起来看看吧,希望各位有帮助。 【目的】:将一个类的...2016-11-25
- 今天做的是个简单的表明表页面,前端我用的是Bootstrap。没办法,自己不懂美工,也只有用别人的工具。BS真的很漂亮,而且插件丰富,不愧是twitter工程师弄出来的东西。 (中...2016-11-25