>백엔드 개발 >PHP 튜토리얼 >PHP의 몇 가지 함정

PHP의 몇 가지 함정

大家讲道理
大家讲道理원래의
2017-03-14 17:07:283163검색

1. 소수점(점의 개수)은 같은지 직접 비교할 수 없습니다

예를 들어 if(0.5+0.2==0.7)의 결과는 false입니다. 그 이유는 PHP는 C 언어를 기반으로 하고 있으며, C 언어는 바이너리 기호점 표현으로 인해 대부분의 기호점을 정확하게 표현할 수 없기 때문입니다. 사실 거의 모든 프로그래밍 언어가 십진수(점으로 구분된 숫자)를 정확하게 표현하지 못하는 것이 일반적인 현상인데, 이는 IEEE 754의 결함이기 때문입니다. 이 문제를 해결하기 위해서는 또 다른 표준을 세울 수 밖에 없습니다. 오직 Mathematica만이 이 문제를 해결한 것 같습니다.

2. 문자열이 동일한 경우 == 대신 ===를 사용하는 것이 좋습니다.

왜? 이 비교는 약한 유형이므로 두 가지 비교가 이루어질 때 PHP는 먼저 왼쪽과 오른쪽이 숫자인지 확인하려고 시도합니다. 문제는 숫자가 어떤 종류의 문자열인가요? 단순한 숫자의 문자열인가요? 그 외에도 0x로 시작하는 16진수, XXeX 유형의 과학적 표기법 등도 포함됩니다. 예를 들어 '12e0'=='0x0C'는 true가 됩니다. 숫자 유형을 문자열과 비교할 때 12=='12 this string'과 같이 숫자로 시작하는 일부 숫자가 아닌 문자열도 true가 됩니다.

따라서 이러한 경우 동일하지 않은 문자열은 동일한 것으로 판단될 수 있습니다. ===를 사용한 비교는 변환이 없는 포괄적 유형 비교이므로 문자열이 동일한지 정확하게 비교할 수 있습니다.

게다가 JAVA에 대해 불평하고 싶습니다. ==는 문자열이 객체이고 ==가 동일한 객체인지 판단하기 때문에 문자열이 같은지 비교할 수 없습니다.

3. 트림 시리즈 기능의 과도한 제거

트림 기능의 기본 사용법은 가장 바깥쪽 공백, 개행 문자 등을 제거하는 것입니다. 선택적 매개변수로 인해 많은 사람들이 이를 사용하여 ltrim($str, "xEFxBBxBF") rtrim($str, ".txt"); . 그러나 곧 이러한 함수가 더 많은 항목을 제거한다는 사실을 알게 될 것입니다. 예를 들어 원래 접미사를 제거하려는 경우 logtext.txt는 logtext 대신 logte가 됩니다. 왜? 후자의 매개변수는 완전한 문자열이 아니라 문자 목록 을 의미하기 때문에 가장 왼쪽/오른쪽이 이 목록 중 하나와 일치하는지 항상 확인한다는 의미입니다.

그렇다면 첫 번째와 마지막을 어떻게 제거하고 싶습니까? 인터넷에서는 정규식을 사용하라는 말이 있는데, 해당하는 세 가지 방법을 쉽게 사용할 수 있도록 요약해 놓았습니다. 명명 규칙은 원래 PHP 함수보다 문자열을 의미하는 s가 하나 더 있다는 것입니다. 사용법은 기존 PHP 함수와 동일합니다.

으아아아
4. 인터넷에 언급된 클라이언트 IP 주소를 얻는 다양한 방법

클라이언트 IP 주소를 얻기 위해 인터넷에서 널리 사용되는 PHP 함수는 다음과 같습니다.

으아아아

这函数看起来并没有什么问题,很多开源CMS之类的也在用。然而事实上,问题大着呢!首先第一步,是要了解这些 getenv 读取的东西到底是什么玩意,又是从哪来的。简单来说这些其实是HTTP header,有些代理服务器会把源请求地址放到header里,所以我们服务器可以知道访问用户的原始IP地址。但是,并不是所有代理服务器都会这么做,也并不是只有代理服务器会这么做。

而实际上,这些HTTP header是可以随便改动的,比如curl就可以自己设置各种HTTP header。如果用此函数得到的结果,进行IP限制等操作的话是很轻易绕过的。更可怕的是,如果后续程序没有对此函数取得的IP地址进行格式校验过滤的话,就很微妙地为SQL注入打开了一扇窗户。所以比较保险的方式是只读取非HTTP header的  $_SERVER['REMOTE_ADDR'] 

PHP5.4及以上可以使用以下函数判断是否符合IP地址格式 filter_var($ip, FILTER_VALIDATE_IP) ,老版本需自行写正则。

五、foreach的保留现象

使用   foreach($someArr as $someL){ }  之类的用法时,要注意最后的一个 $someL 会一直保留到该函数/方法结束。而当使用引用的时候  foreach($someArr as &$someL){ }这是以引用来保存,也就是说后面若有使用同一个名字的变量名,将会把原数据改变(就像一个乱用的C指针)。为安全起见,建议每个foreach(尤其是引用的)结束之后都使用unset把这些变量清除掉。

foreach($someArr as &$someL){    //doSomething ...}unset($someL);

六、htmlspecialchars 函数默认不转义单引号

不少网站都是使用此函数作为通用的输入过滤函数,但是此函数默认情况是不过滤单引号的。这是非常非常地容易造成XSS漏洞。这样的做法和不过滤双引号没太大区别,只要前端写得稍微有点不规范(用了单引号)就会中招。下面这个示例改编自知乎梧桐雨的回答4110a9844baef9d25a82ccef3094ed14

  ' />

要求所有的时候都使用双引号不得使用单引号,这其实不太现实。所以,这个主要还是后端的责任,把单引号也要转义,我们用的时候一定要给这个函数加上参数  htmlspecialchars( $data, ENT_QUOTES);

很多人向Thinkphp框架提出过这个问题,因为其默认过滤方法就是无参数的htmlspecialchars,不过滤单引号,而其官方答复是“I函数的作用不能等同于防止SQL注入,可以自定义函数来过滤”……毛线啊,最基本的防护都不给力,这是给埋了多少隐患啊。在此强烈各位使用者重新定义默认过滤函数,我自己定义的是 htmlspecialchars(trim($data), ENT_QUOTES); ,有更好建议欢迎评论。同时非常希望TP官方更正此问题。

 

关于XSS,容我多说两句,请看下面这个例子。

<span style="color:#ff00ff;"><?</span><span style="color:#ff00ff;"><span style="color:#000000;"><span style="color:#ff00ff;">php</span> $name='alert(1)';</span> </span><span style="color:#ff00ff;">?></span><span style="color:#0000ff;"><</span><span style="color:#800000;">p </span><span style="color:#ff0000;">id</span><span style="color:#0000ff;">="XSS2"</span><span style="color:#0000ff;">></</span><span style="color:#800000;">p</span><span style="color:#0000ff;">></span><span style="color:#0000ff;"><</span><span style="color:#800000;">script </span><span style="color:#ff0000;">src</span><span style="color:#0000ff;">="//cdn.batsing.com/jquery.js"</span><span style="color:#0000ff;">></</span><span style="color:#800000;">script</span><span style="color:#0000ff;">></span><span style="color:#0000ff;"><</span><span style="color:#800000;">script</span><span style="color:#0000ff;">></span><span style="background-color:#f5f5f5;color:#000000;">$(</span><span style="background-color:#f5f5f5;color:#000000;">"</span><span style="background-color:#f5f5f5;color:#000000;">#XSS2</span><span style="background-color:#f5f5f5;color:#000000;">"</span><span style="background-color:#f5f5f5;color:#000000;">)[</span><span style="background-color:#f5f5f5;color:#000000;">0</span><span style="background-color:#f5f5f5;color:#000000;">].innerHTML </span><span style="background-color:#f5f5f5;color:#000000;">=</span> <span style="background-color:#f5f5f5;color:#000000;"><?=</span><span style="background-color:#f5f5f5;color:#000000;">$name</span><span style="background-color:#f5f5f5;color:#000000;">?></span><span style="background-color:#f5f5f5;color:#000000;">;
$("#XSS2").html( <?=$name?> );
$(</span><span style="background-color:#f5f5f5;color:#000000;">"</span><span style="background-color:#f5f5f5;color:#000000;">#XSS2</span><span style="background-color:#f5f5f5;color:#000000;">"</span><span style="background-color:#f5f5f5;color:#000000;">)[</span><span style="background-color:#f5f5f5;color:#000000;">0</span><span style="background-color:#f5f5f5;color:#000000;">].innerHTML </span><span style="background-color:#f5f5f5;color:#000000;">=</span> <span style="background-color:#f5f5f5;color:#000000;">"</span><span style="background-color:#f5f5f5;color:#000000;"><?=$name?></span><span style="background-color:#f5f5f5;color:#000000;">"</span><span style="background-color:#f5f5f5;color:#000000;">;
$("#XSS2").html(" <?=$name?> ");</span><span style="color:#0000ff;"></</span><span style="color:#800000;">script</span><span style="color:#0000ff;">></span>

JS의 첫 번째와 두 번째 줄은 XSS 취약점을 유발하지만 세 번째와 네 번째 줄은 그렇지 않습니다. alert(1)의 경우 백엔드에서 이러한 문자열을 필터링하는 더 좋은 방법은 데이터의 양쪽 끝에 따옴표를 추가하는 것입니다. 주요 책임은 여전히 ​​프론트엔드에 있습니다. innerHTML 및 jQuery의 html() 출력을 사용할 때는 다음 사항을 확인하세요. 전달된 매개변수는 문자열입니다. 그렇지 않으면 평가 함수만큼 위험합니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.