月度归档:2011年01月

安全?安全!安全!!

安全?安全!安全!!
在某日下班后,回家的路上,一个人走,走着走着,忽然我的手碰到了另一支手,艳遇?扭头!发现一新疆美男在左顾右盼。然而我背的包已经被拉开了一半。好险,我的kindle,钱包都在包里。

年关将近,是该注意安全了。特别是回家的路上,请各位兄弟照顾好贵重物品和老婆,防火防盗啊!

好吧,言归正转。我们还是说说我们在开发中的安全问题吧。

这里我们从一次PHP请求过程来说明一些常见的安全问题。

【从客户端到服务器应用层】
每次用户的请求都会先通过客户端发起请求,然后服务器接收请求并处理这个请求。
如果我们在客户端有验证(如必须输入用户名之类的),此时我们除了在客户端验证外,更重要的是在服务器的应用层进行验证(所有的验证必须在服务器有一份)。这些验证包括不能为空,输入内容的长度,输入内容的类型等。如果确定为数字型,可以考虑将其转化为数字类型后使用。
为什么要这样做呢?因为我们不相信客户端,也不相信客户端的验证。在某些情况下,对于用户输入的数据,我们不仅仅是过滤,在必要的时候可能需要直接提示用户输入错误。
如果我们在实际项目中要做类似于投票的功能,需要对用户进行限制,常规的,ip,验证码等。除此之外,如果是基于某个已有应用,并且这个应用是有账号这个概念的,那么我们可以加入基于账号的验证;如果整个投票活动是基于某个活动流程,那么我们也可以加入流程验证。

【从应用层到数据层】
在应用层接收到客户端的数据后,如果此时我们需要查询后台的数据进行相关计算,那么我们需要调用数据层获取数据,当把参数传给数据层后,数据层应该不相信应用层的数据,它需要按照自己的逻辑进行类型等的验证,然后再将查询的条件传给数据库。
这样也许可以减少一些SQL注入漏洞。

【从服务器应用层到客户端展示】
当应用层从数据层获取数据处理完后,需要在前台展示,此时会将计算结果返回给客户端。
在显示计算结果之前我们需要将计算结果进行过滤。因为我们不相信服务器(或者说数据层)返回给我们的信息。对,不相信他们。
这样也许可以减少一些存储式跨站脚本漏洞。

【服务器本身的问题】
就PHP本身而言,一些必要的参数,安全模式的开启。比如php.ini中的open_basedir参数。
或者在开发机器经常看到可以浏览整个目录的情况。
或者PHP中的打开register_globals(新的版本默认为关闭)

所有的说到底就一个原则:不要相信任何人!
此时想起了面向对象中的迪米特法则:不要和陌生人说话。
也许没有什么关联,只是在某些点上,大道相通。

Yii框架中有点意思的文件缓存

Yii框架中有点意思的文件缓存

在Yii框架的framework/caching目录下是Yii框架的所有缓存操作。包括文件缓存,APC缓存、Db缓存,Memcache缓存等。 今天我们要说的是文件缓存。

【文件和类结构】

它总共包括CFileCache.php、CCache.php和接口文件。 缓存基类CCache抽象类实现了CApplicationComponent类,ICache, ArrayAccess接口。 实现类CFileCache继承自CCache基类。其它如Memcache等缓存也是继承这个基类。 在ICache接口中统一缓存接口,在CCache基类中统一对外的接口,以类似于模板方法模式的方式将对于增加,修改,删除操作延迟到子类实现。

【缓存方案】

指定缓存目录,以一条数据一个文件的方式存储。序列化使用PHP自带的serialize函数。 如果缓存数据过多,作者建议使用多级目录,多级目录会自动生成,默认为0,即当前目录,推荐使用3级以下的子目录。 对于缓存过期是以文件的修改时间为准(filemtime函数)。在获取数据时,如果文件过期,则取的数据为空。

【有点意思的地方】

个人觉得有点意思的地方在于其对于过期缓存的批量处理,在程序中作者称其为garbage collection。 看其实现代码:

if(!$this->_gced && mt_rand(0,1000000)<$this->_gcProbability)
{
    $this->gc();    //  清除过期的缓存文件
    $this->_gced=true;
}

各位看官,你应该知道这段代码是啥意思了。 有点意思的地方是和PHP源码中对于session过期的处理。如下所示源码:

if (PS(mod_data) && PS(gc_probability) > 0) {
    int nrdels = -1;

    nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C));
    if (nrand < PS(gc_probability)) {
        //  调用定义的垃圾收集方法
        PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels TSRMLS_CC);
        ...
    }
}

对比下变量名,对比下调用方式。 ^_^

TIPI0102–PHP源码结构、阅读代码方法

第二节 PHP源码结构、阅读代码方法

PHP源码目录结构:


俗话讲:大巧不工。PHP的源码在结构上非常清晰甚至简单。下面,先简单介绍一下PHP源码的目录结构。

  • build: 源码编译相关文件,包括buildconft等sh文件,还有一些awk的脚本。
  • ext 官方扩展目录,包括了绝大多数PHP的函数的定义和实现,如array系列,pdo系列,spl系列等函数的实现,都在此处相对的子目录中。
  • main PHP宏定义与实现,在需要扩展PHP时,经常要使用的PHP_*系列宏就在这里定义。
  • Zend 包含Zend引擎文件,Zend API宏的定义和实现。
  • pear “PHP 扩展与应用仓库”, 包含PEAR的核心文件。
  • sapi 包含了各种服务器抽象层的代码,以目录区分。
  • TSRM “线程安全资源管理器” (TSRM) 目录。
  • tests 测试脚本目录。
  • win32 Windows 下编译PHP相关的脚本。

PHP源码阅读方法:


使用VIM + Ctags查看并追踪源码:

VIM是一个非常给力的编辑器,在纯命令终端下,它几乎是无可替代的(Emacs?)。
ctags可以将源代码中的各种函数、宏等信息做上标记。这样,使用VIM就可以很方便的查看源码。
简洁使用说明:

#在PHP源码目录(假定为/server/php-src)执行:
$ cd /server/php-src
$ ctags -R

#在~/.vimrc中添加:
set tags+=/server/php-src/tags

再用vim打开各种php源码文件时,将光标移到想查看的函数、宏、变量上面, 使用 Ctrl+p 就可以自动跳转至定义,Ctrl+o 可以返回上一次查看位置。

使用Visual Studio + editplus查看并追踪源码:

看源码还是用IDE舒服一些,windows下我们还是用Visual Studio 2010看吧。 在win32目录下已经存在了可以直接打开的工程文件,如果由于版本原因无法打开,可以在此源码目录上新建一个基于现有文件的Win32 Console Application工程。
常用快捷键

F12 转到定义
CTRL + F12转到声明

F3: 查找下一个
Shift+F3: 查找上一个

Ctrl+G: 转到指定行

CTRL + -向后定位
CTRL + SHIFT + -向前定位

对于一些搜索类的操作,可以考虑使用editplus或其它文本编辑工具进行,这样的搜索速度相对来说会快一些。
如果使用editplus进行搜索,一般是选择 【搜索】 中的 【在文件中查找…】

作者:TIPI Team