博客技术总结
关键词:博客,Blog
作者:BIce 创建时间:2012-07-22 01:59:21
在今年写完这个博客的时候,就一直想总结下在做博客的过程中学到的新东西,最近好算挤出时间,就简单的总结一下。博客用的基本技术还是之前说过的PHP+Zend Framework,不同的是服务器虽然最开始的时候用的是主机,后来就换成了SAE的服务,挺好的哈,对新浪赞一下。
下面开始介绍博客里面用到的一些东西,主要分为:权限控制和地址检查;定时任务;三级页面展现;留言功能以及验证码功能。
下面给出博客用户导航界面如下
1. 权限控制与访问地址检查
权限控制室所有网站都会考虑的问题,由于本博客功能有限,故需要顾及的权限控制也就少一些,大致分为两个方面:
- 以一个页面作为控制的最低粒度资源(也可以不是页面,一个Controller+Action的组合)
- 限制未登录用户对目标资源进行查看
- 限制登陆的不同用户对其他人的资源进行修改(博客的设计上支持多用户,虽然只有自己和老婆用..)
关于这两种可能的越权访问情况,我采用的处理方案如下:
- 我们都知道Zend Framework使用的是前端控制器的MVC模式,为了对所有的请求都进行过滤和检查处理,我实现了一个叫做BasicController的Action类,作为所有其它Controller的父类,并将权限设置和检查都在此类中进行。
- 在BasicContrpller的init函数中,我们对其他所有Controller都要使用的变量进行初始化,如:数据库访问对象,Session区域信息如用户登录信息等等。
- 在BasicController类中声明一个priviledgeTable静态变量,里面存储了每个Controller的Action集合,其中每个Action都对应一个数组,其中存储着需要的限制(限制未登录用户、限制虽登录但不是同一用户),如仅包含BlogController的priviledgeTable声明如下:
public static $priviledgeTable=array("blog"=>array("detail"=>array(),"new"=>array("visit"),"add-blog"=>array('visit'),"modify"=>array('userMatch'),"update-blog"=>array('userMatch'),"delete-blog"=>array("userMatch"),"category"=>array(),"index"=>array('visit')));
- 在BasicController的preDispatch函数中,我们加入了对权限加以控制的代码:(注意首句的accessInsert函数调用,它负责对访问信息进行存储,保存到表中。)
首先,根据参数获取本次访问的controller和action,检查priviledgeTable中的具体限制,如果没有找到对应项,就说明用户访问了根本不存在的页面,直接设置错误信息并重定向到错误界面;有对应项的情况,如果无限制则返回,有限制,则会调用相应的限制函数,这里的限制函数目前只有两个,visitCheck和userMatchCheck,其中任何一个限制函数返回False都会直接重定向到错误页面提示权限错误。
- visitCheck函数:负责检查Session信息,检查是否有登录信息,如无则返回Fasle,检查不通过。
- userMatch函数:负责检查针对某个表资源,其从属用户(具体针对每个表要独立实现如何查询从属用户的功能)是否是目前登录的用户,如果没有登录或者登录用户不匹配则返回False,检查不通过。
以上就是本博客所使用的权限检查和访问地址检查的方案,很是简单,期待大家批评
2. 定时任务
由于各种需要,博客也需要一些定时执行的任务如:
- 每天凌晨生成本天的日报报表
- 每周周末生成本周的待填周报
- 每周周末生成本周日报报表汇总
- 每隔几个小时对验证码存储目录进行清空操作
- 每隔一段时间对代码和数据库的备份
以上是本博客使用的一些定时任务,这些定时任务针对不同的平台有不同的实现方法。如果是使用的Linux系统,则可以使用Crontab命令来实现,如果是使用SAE的话,也可以使用SAE提供的Cron服务进行处理。
3. 三级页面处理
在博客的界面中,导航方式比较简单,没有出现复杂的导航形式,而针对比较复杂的页面,很有可能出现两级级导航页面,也就是上方一个导航栏,左边一个导航栏,而真正显示内容的地方在右中侧,在这种情况下,我们一般不希望在每次选择三级页面的时候,都刷新其他的内容,或者重新加载一遍页面,最好的方式是只对需要更改的右侧内容进行刷新,达到这种效果可能的解决方案我找到两种,下面分别说明:
- 采用Iframe标签
此种方案需要首先创建一个Iframe标签,对其大小位置进行调整,用以装载具体的三级页面,然后将二级导航栏(左侧)导航的链接加上一个Target属性,指向具体的页面,这样,在具体进行页面选择之时,除了Iframe部分加载新页面,其他的内容都不会刷新,这样就达到了我们要的效果。不过这个方案的方法是一个Iframe加载的内容也是一个独立的HTML页面,变成了与外部页面不相关的东西,对于它的可控性就差一些。
- 使用AJAX,动态创建内容
此方案与上一个不同,此方案几乎全部代码都由JavaScript完成即可,首先创建一个Div标签,对其大小位置进行调整,用以存放具体的三级页面。然后将左侧的二级导航栏的A标签加入onclick事件的响应函数,进行一个AJAX的调用,请求后台传递具体展现三级页面需要的数据,在AJAX的回调函数中,使用JS创建具体的三级页面展示内容,然后挂载到事先建好的DIV上,这样具体的页面内容就展现出来了,而且也没有页面的刷新。这种方法的缺点是实现其他比较复杂,需要比较多的JS代码,而且不容易被别人理解。
上述两种方法仅供大家参考,根据不同情况可以使用不同方案,但比较推荐第一种,原因是上手简单且易理解。
4. 留言功能
说到博客,就肯定要给大家一个留言,相互交流的方式。而大家的留言有时是针对某条其他人的留言的,可能是个树型的结构。这也就需要我们在设计留言功能的时候,需要考虑留言和留言之间的针对关系,涉及到的设计有这么几方面:
- 在留言的数据库表设计上,要给出一个自己链接到自己的外键,用于指定这种针对关系。
-
在留言的具体界面上,要给出一个可以针对某条留言进行回复的方式,这里本博客的实现方法如下
- 使某条博客的具体留言按照留言ID(自增的字段)进行展现。
- 在每条留言处后面,给出一个回复按钮,点击此按钮,就根据点击留言的ID,记录想要回复的具体某个留言,并在界面中以回复#X楼的提示展现出来(当然要提供取消回复以便修改回复对象的功能)。
- 在提交留言请求的时候,程序将留言针对的ID一起发送出去,由后台生成留言数据并保存其对应关系(然后根据具体针对留言的信息,比如有邮箱的设置,就给被回复的人邮箱发送一封邮件,告知留言被回复,但为防止大家被邮件骚扰到,邮件一天仅会对一个邮箱发一封),在展现留言的过程中,如果发现其是针对某条留言的,根据顺序给出具体的回复指向。
恩留言功能就说到这,如果想看具体效果的话,大家可以去某篇博客的最下面,猛击留言吧。
PS: 博主真的越来越发现,看帖不留言的都是坏银。。
5. 验证码
说到做验证码,起初是不想做的,因为感觉比较麻烦,后来有一天发现本来一直没什么人访问的博客突然有了人气爆棚的场面,好多访问量,当时一阵狂喜,后来发现是国外的某个无聊人士用机器在刷我的博客,并且在向我的留言系统注入很多广告类的垃圾信息。无奈在删了几天之后,决定重复造下轮子,自己做个验证码的组件,验证码做完的三四天后,博客就安静了。。也一下子就回到了没有人看的场面。下面简单介绍下验证码的实现步骤:
- 实现验证码图片的生成
- 我们都知道,验证码只不过是一张由程序产生的图片,里面有一些人类可以看懂但机器很难看懂的信息(当然,由于各种破解算法的出现,能做到不让计算机识别出来的验证码已经是比较难的技术了,不过我一个小博客,应该没人无聊到来破解我的验证码吧..)。
- 而这些图片,也就是一些字母和数字的旋转、扭曲,再加上一些干扰的因素而已,我的实现也是如此,我的字符集是从0-9, a-z, A-Z的这些字符,每个验证码图片包含4-6个字符,其中我对这些字符进行了一些随机的旋转,并且在每个字符的放置位置上也做了相应的偏移。
- 最后,我通过向图片中加入一些干扰因素:一些随机位置的点和几条随机位置的线段,来对验证码防破解功能进行加强。然后就调用图形库,将验证码存储到了临时文件夹中。
上代码吧
- 获取验证码
在前台获取验证码方面,我们一样使用AJAX调用完成。前台向后台请求一个验证码,后台根据当前的session_id(或者是一个随机数)来命名并生成一个临时验证码文件,放入到一个临时目录中,返回给前台最后的验证码图片地址,同时将生成的验证码实际字符串放入到Session中,以备后续与用户的输入对比。代码如下:
- 展现验证码
前台通过一个AJAX请求,获取了刚刚生成的验证码图片地址,只要将显示验证码的Img标签的src指向这个地址即可。但如果你是用session_id作为图片的文件名的话,这样动态更换验证码的时候,由于Img的src属性没有变化,虽然设置了src属性,但是不同的浏览器的行为不同,有的浏览器不会刷新图片(因为src实际是没有变化的),这时可以使用在Img的src属性的文件名后面每次加上一个?rand=XX,指定一个随机参数的形式,这样虽然src属性内容未变,但所有浏览器都会由于随机数的不同而刷新新图片了。
代码如下:
另外需要注意的是,在每次打开一个需要验证码的页面的时候,都需要强制请求一次重新获取验证码的操作,这样是防止用户验证码始终是一个,没有被更新的情况。而由于验证码会产生临时文件,而此文件的生命周期又一般来说很短,所以为了防止验证码文件泛滥,可以使用一个定时任务定期(每一个小时)清理一下验证码文件夹以节省空间。
如上所讲,验证码部分也就讲完了,本博客的实现还是比较简单的,也会比较容易被攻破,但本着学习态度做一下也挺好,如果你真的需要高强度的验证码或者不想自己写的话,可以使用一些开源的验证码项目,有很多,就不列举了
关于本博客的一些总结记录也就到此结束了,其他使用的Zend Framework以及Dojo部分之前已经在其他博客中说明。还有一点忘了说,我不擅长写DIV和CSS对网站进行美观布局,因此本博客的CSS是用的网上的开源的资源,争取以后换成自己的吧