当前位置:  开发笔记 > 编程语言 > 正文

一步步编写PHP的Framework(十三)

上次讲到控制器怎么样将数据传递到视图,今天我就主要说一下在程序中怎么让代码更安全,之后就转到讲模型,再讲怎么做视图,最后再讲控制器的功能强化。我再声明一下,我写这个文章只是让大家对PHP的框架编...">

 

上次讲到控制器怎么样将数据传递到视图,今天我就主要说一下在程序中怎么让代码更“安全”,之后就转到讲模型,再讲怎么做视图,最后再讲控制器的功能强化。

      我再声明一下,我写这个文章只是让大家对PHP的框架编写有一个基本的了解,由于本人技术有限,这个文章是给PHP初学者学习的,所以高手勿喷,还有就是我现在时间也有限,所以每次可能需要两三天才能写一篇,每篇我写的时间也要控制在一个小时以内,由于边写这个文章边编代码,所以代码中可能会存在很多BUG,见谅!!

       如果你是一个PHP爱好者,请在文章后面积极回复一下,这种交流不仅可以使我的PHP技术提高,也鼓励了我继续写下去的勇气,谢谢!!

       很多人编写PHP代码什么都不注意,遇到很多警告,就直接通过error_reporting屏蔽掉,这样做我觉得问题是非常大的,比如:

1
2    $a = $_GET['a'];
1 echo $a;

      如果通过GET方式传递的参数有a,那么程序非常正常,但是如果没有传递呢,那就会抛出一个警告!!

      我的作法是首先将error_reporting设置为E_STRICT,不允许程序出现警告!!

      刚才这段代码可能就需要修改成:

1
2 $a = isset($_GET['a']) ? $_GET['a'] : '';
1 echo $a;

       除了这种问题,还有就是PHP特有的 @符号 ,很多人都喜欢用这个来屏蔽错误,但是我觉得使用这个弊大于利,因为当项目很大的时候,出现一个错误,由于这个错误又被屏蔽,要找到这个错误的位置真心的很难!!

 

       关于异常的处理,虽然try catch会带来很大的开销,我个人觉得为了程序的健壮性,必要的try catch还是需要的。

       好吧,杂七杂八的说了这么多,貌似这个和安全不太沾得上边,但对于我来说,它们也是“安全”的一部分。

       现在假设你花费了十天时间编写了一个简单的博客系统,购买了万网的虚拟主机或VPS,申请域名,网站备案,然后部署代码,这一切的一切都搞定了,然后用户就可以通过比如www.test.com这样一个域名来访问你的博客系统,你这套博客系统很受欢迎,短时间内就积累了大量的人气,但是突然有一天,你发现你的网站突然出故障了,你怎么办?

       在线上将PHP的配置文件中的error_reporting打开,然后线上调试?

       说实话,我之前也在我的博客系统上面线上调试过,和上述情况不一样的一点是,我的博客访问量很低,因为我这个人太懒了,不太喜欢去管理我的博客。

        如果你的网站拥有很大的访问量,你在线上做调试想想也是不可能的事情,那怎么做呢?

        记Log,如果你的网站在发生故障之前你就有写Log,那么程序出现故障之后你只需要打开日志文件,然后就可以看到故障出现的位置,然后修复掉,这样就OK了!!

        好了,现假设我是你的同学,并且也参与了你的博客系统的开发,但是我和你前一阵闹了一点矛盾,我怀恨在心,想把你的博客系统破坏掉,怎么破坏呢?

        首先假设你的数据库名为Test,这个数据库中存在一个user表,user表存放着20000个会员信息,我知道你的博客注册系统的代码是如下:

01
02 $username = $_POST['username'];
03 $password = $_POST['password'];
04 if(empty($username) || empty($password)) {
05      //跳转到注册界面并提示用户名或密码未填写
06      exit();
07 }
08 //连接数据库
09 //假设DB类封装了很多SQL操作,析构的时候自动关闭数据库连接,具体过程不写了
10 //$db是一个数据库DB类的实例,存在两个方法
11 //$db->isUsernameExists判定是否用户名是否存在
12 //$db->query 执行一条SQL语句
13 if(!$db->isUsernameExists($username)) {
14    $db->query("insert into user (username,password) values ('" . $username . "','" . $password. "')");
15    //设置session并跳转
16    exit();
17 } else {
18     //跳转到注册界面并提示用户名已存在
19     exit();
20 }

 

      这段代码有问题吗,我相信很多PHP Coder都会很鄙视的说到“你不就是想说SQL注入嘛”。

      的确,这个就是一个SQL注入的问题,这个问题已经很古老了,好像大家都知道,为什么我还要讲呢?

      这是因为我之前在学校看到过几个由学弟编写的PHP项目,他们就基本上没有考虑过这个问题,很多代码就直接这么写,当然,你如果按照网上SQL注入的方式去试,会发现你根本注入不了,貌似PHP已经自动帮你解决掉这个问题了,怎么解决的呢,实际上就是对特殊字符前加上反斜线。

      首先说一下为什么SQL注入失败呢?如果你的php.ini中配置了自动转义,PHP会在你将数据插入到DB之前对数据进行转义。

      貌似这样我们就不用考虑这个问题了,但是实际上PHP帮我们做了这些才让事情更可怕,如果你将你的程序转移到另外一台linux服务器, 这台服务器上面php.ini配置文件中配置了不自动进行转义,那么你的程序一下子问题就大了,我们不应该将我们代码的安全性依赖于服务器的配置。那么怎么搞定这个事情呢?

      幸好,PHP中已经有了addslashes函数,它会对特殊字符进行转义,但是很遗憾,通过查看PHP手册发现:

       默认情况下,PHP 指令 magic_quotes_gpc 为 on,它主要是对所有的 GET、POST 和 COOKIE 数据自动运行addslashes()。不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测

       那怎么做呢,幸好PHP已经提供了一个get_magic_quotes_gpc函数可以来判定是否已经开启了magic_quotes_gpc,所以我们可以自定义一个addslashes函数,如:

1
2 function myAddslashes($str) {
3     if(get_magic_quotes_gpc()){
4            return addslashes($str);
5     }
6 }

       其实还有另外的方法解决这个问题:

 

       1. 使用PDO来访问DB,PDO中可以使用PDOStatement->bindParam,这样,PDO会自动帮你做好这一切,并且我个人觉得PDO很有前途!!

       2. 如果get_magic_quotes_gpc为on,首先调用stripslashes去除转义字符,然后在插入数据库之前使用mysql_real_escape_string,我个人觉得这种方式比第一种方式靠谱!!

      当然,说了这么多,有可能还有童鞋不知道什么是SQL注入,我就简略的讲一下SQL注入的过程啊,熟悉SQL注入的人直接pass掉这一段。

      按照上面的例子,假设用户在password这个字段输入的值为a');drop table user;...,那么执行SQL的时候SQL语句就会变成:

          insert into user (username,password) values ('用户名','a');drop table user;...')

     这个SQL首先会向user表插入一条记录,然后删除整个表,然后。。。。SQL出错了。

     不过不管SQL是否出错,user表已经没有了,对于一个会员10000的博客,用户表没有了,我觉得损失还是蛮大的,当然,你也可以将连接数据库的用户的权限降低,没有删除表的权限,但是这样也不是一个治本的方法,还是解决掉SQL注入漏洞比较靠谱。

      好,解决掉SQL注入,我再说一下XSS(跨站脚本漏洞)的问题。

      现有一段PHP的脚本:

1
2 echo $_GET['a'];

      我才讲到这个的代码是有问题的,上面说的是有时候会抛出警告,但是如果传递参数的时候被不法分子利用,这个问题就大多了。

 

      现在假设访问这个脚本的URL是:http://localhost/test.php?a=a,我将参数a的值设为a,传递过去一点问题都没有吧,但是现在假设我值换一下,URL变成了:

      http://localhost/test.php?a=,那么执行脚本的时候就会跳转到天猫首页,这样恐怖吧!!

      如果这个不是跳转到天猫,而是跳转到某一个黑客设好的网址,他就可能将你的COOKIE信息弄到,然后就可以伪造COOKIE,用你的身份登录博客系统,然后。。。。你懂的。

      解决这个问题的方法也很简单,就是字符串转义就OK,实际上就可以通过我们自定义的这个myAddslashes方法来做,调用了这个方法之后,脚本无法执行了,但是有时候我们又需要执行脚本,那怎么做呢,我们可以对输入的字符串按照一定的规则过滤,具体怎么使用的可以参照手册。

      解决掉这个问题之后,我再说另外一个问题,这个问题就是CSRF(跨站点请求伪造漏洞),这是个什么东东!!!

      现假设你有一个留言的系统,留言的内容是富文本的,用户可以添加表情等等,表情的HTML代码是,假设用户填写的表情是通过你提供的富文本编辑器来做的,没有任何问题,但是如果他不使用这个,而是利用img标签做了另外一个事情呢?

      怎么做呢?很简单的,就是改变img标签的src属性:

     

       提交留言之后发现这个图片无法显示,为什么无法显示其实也很简单,根本不是一个合法的图片链接,但是当一个不知情的用户A查看留言的时候,会发生什么情况,每次用户打开这个留言的页面,实际上就会访问www.tmall.com一次,如果将这个网址改成黑客的网址,那么结果,还是你懂的。。。

        其实除了这些,还有上传文件的漏洞等等,由于时间有限,就不说了。

        我讲这些实际上就是为了说明,安全问题实际上很重要,我们在编程序的时候要考虑的东西实际上是很多的。

        本来今天还要讲怎么在框架中怎么去解决这些问题,但是又超出我预计的一个小时的时间了,那就下次再说了。


推荐阅读
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文首先对信息漏洞的基础知识进行了概述,重点介绍了几种常见的信息泄露途径。具体包括目录遍历、PHPINFO信息泄露以及备份文件的不当下载。其中,备份文件下载涉及网站源代码、`.bak`文件、Vim缓存文件和`DS_Store`文件等。目录遍历漏洞的详细分析为后续深入研究奠定了基础。 ... [详细]
  • Web自动化测试:表单提交与页面跳转的高效实现
    Web自动化测试:表单提交与页面跳转的高效实现 ... [详细]
  • 题目描述非常吸引人。每颗星星可以通过其在窗口的左下角和右上角位置构建两条扫描线,从而将问题转化为区间增减和求最大值的操作。需要注意的是,位于边界的星星不应计入结果,因此在处理时应分别对左右边界进行适当的增减调整。此外,利用线段树和离散化技术可以显著提高算法效率,确保在大规模数据下的性能表现。 ... [详细]
  • 本文探讨了如何在C#中实现USB条形码扫描仪的数据读取,并自动过滤掉键盘输入,即使不知道设备的供应商ID(VID)和产品ID(PID)。通过详细的技术指导和代码示例,展示了如何高效地处理条形码数据,确保系统能够准确识别并忽略来自键盘的干扰信号。该方法适用于多种USB条形码扫描仪,无需额外配置设备信息。 ... [详细]
  • 在《PHP应用性能优化实战指南:从理论到实践的全面解析》一文中,作者分享了一次实际的PHP应用优化经验。文章回顾了先前进行的一次优化项目,指出即使系统运行时间较长后出现的各种问题和性能瓶颈,通过采用一些通用的优化策略仍然能够有效解决。文中不仅详细阐述了优化的具体步骤和方法,还结合实例分析了优化前后的性能对比,为读者提供了宝贵的参考和借鉴。 ... [详细]
  • Vuex 实战进阶:构建高效笔记本应用(第二篇)
    在上一篇文章中,我们初步探讨了 Vuex 在该项目中的应用。本文将深入解析整个项目的架构设计。首先回顾 `main.js` 的内容,然后重点分析 `App.vue` 文件,其中引入了 `Toolbar.vue` 和 `NodeList.vue` 组件,详细说明它们在应用中的作用和交互方式。通过这些组件的协同工作,我们将展示如何构建一个高效且响应迅速的笔记本应用。 ... [详细]
  • Photoshop教程第五讲:使用套索工具精准抠图技巧
    在本节Photoshop教程中,我们将深入探讨如何利用套索工具实现精准的图像抠图。通过详细的操作步骤和实用技巧,帮助用户掌握套索工具的多种使用方法,提升图像处理的精细度和效率。 ... [详细]
  • 本文详细解析了如何使用 jQuery 实现一个在浏览器地址栏运行的射击游戏。通过源代码分析,展示了关键的 JavaScript 技术和实现方法,并提供了在线演示链接供读者参考。此外,还介绍了如何在 Visual Studio Code 中进行开发和调试,为开发者提供了实用的技巧和建议。 ... [详细]
  • React组件是构成用户界面的基本单元,每个组件都封装了特定的功能和逻辑,具备高度的独立性和可复用性。通过将不同大小和功能的组件组合在一起,可以构建出复杂且功能丰富的页面,类似于拼图游戏中的各个部分,最终形成一个完整的视觉效果。 ... [详细]
  • 在面对不确定性的挑战时,卓越的操作者通常会采用七大策略来有效管理和减轻风险,这些策略同样适用于职业发展和个人生活。具体而言,这七大风险管理策略包括:1. 克服恐惧心理卓越的操作者能够正视并克服内心的恐惧,保持冷静和理性,从而做出更加明智的决策。这一能力不仅有助于在市场波动中保持稳定,也能在职业生涯和个人生活中发挥重要作用。 ... [详细]
  • 《题画山水屏风》译文与原文赏析:唐代诗人张九龄的艺术解读 ... [详细]
  • 《已亥杂诗 第139首》译文与原文鉴赏:清代文学家龚自珍的诗歌艺术探析 ... [详细]
  • 配置未被正确应用:导航栏图标设置失效问题分析与解决 ... [详细]
author-avatar
仲颖凯翰奕颖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有