1. 소수점(점의 개수)은 같은지 직접 비교할 수 없습니다
예를 들어 if(0.5+0.2==0.7)의 결과는 false입니다. 그 이유는 PHP는 C 언어를 기반으로 하고 있으며, C 언어는 바이너리 기호점 표현으로 인해 대부분의 기호점을 정확하게 표현할 수 없기 때문입니다. 사실 거의 모든 프로그래밍 언어가 십진수(점으로 구분된 숫자)를 정확하게 표현하지 못하는 것이 일반적인 현상인데, 이는 IEEE 754의 결함이기 때문입니다. 이 문제를 해결하기 위해서는 또 다른 표준을 세울 수 밖에 없습니다. 오직 Mathematica만이 이 문제를 해결한 것 같습니다.
왜? 이 비교는 약한 유형이므로 두 가지 비교가 이루어질 때 PHP는 먼저 왼쪽과 오른쪽이 숫자인지 확인하려고 시도합니다. 문제는 숫자가 어떤 종류의 문자열인가요? 단순한 숫자의 문자열인가요? 그 외에도 0x로 시작하는 16진수, XXeX 유형의 과학적 표기법 등도 포함됩니다. 예를 들어 '12e0'=='0x0C'는 true가 됩니다. 숫자 유형을 문자열과 비교할 때 12=='12 this string'과 같이 숫자로 시작하는 일부 숫자가 아닌 문자열도 true가 됩니다.
따라서 이러한 경우 동일하지 않은 문자열은 동일한 것으로 판단될 수 있습니다. ===를 사용한 비교는 변환이 없는 포괄적 유형 비교이므로 문자열이 동일한지 정확하게 비교할 수 있습니다.
게다가 JAVA에 대해 불평하고 싶습니다. ==는 문자열이 객체이고 ==가 동일한 객체인지 판단하기 때문에 문자열이 같은지 비교할 수 없습니다.
트림 기능의 기본 사용법은 가장 바깥쪽 공백, 개행 문자 등을 제거하는 것입니다. 선택적 매개변수로 인해 많은 사람들이 이를 사용하여 ltrim($str, "xEFxBBxBF") rtrim($str, ".txt"); . 그러나 곧 이러한 함수가 더 많은 항목을 제거한다는 사실을 알게 될 것입니다. 예를 들어 원래 접미사를 제거하려는 경우 logtext.txt는 logtext 대신 logte가 됩니다. 왜? 후자의 매개변수는 완전한 문자열이 아니라 문자 목록 을 의미하기 때문에 가장 왼쪽/오른쪽이 이 목록 중 하나와 일치하는지 항상 확인한다는 의미입니다.
그렇다면 첫 번째와 마지막을 어떻게 제거하고 싶습니까? 인터넷에서는 정규식을 사용하라는 말이 있는데, 해당하는 세 가지 방법을 쉽게 사용할 수 있도록 요약해 놓았습니다. 명명 규칙은 원래 PHP 함수보다 문자열을 의미하는 s가 하나 더 있다는 것입니다. 사용법은 기존 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($someArr as $someL){ } 之类的用法时,要注意最后的一个 $someL 会一直保留到该函数/方法结束。而当使用引用的时候 foreach($someArr as &$someL){ }这是以引用来保存,也就是说后面若有使用同一个名字的变量名,将会把原数据改变(就像一个乱用的C指针)。为安全起见,建议每个foreach(尤其是引用的)结束之后都使用unset把这些变量清除掉。
foreach($someArr as &$someL){ //doSomething ...}unset($someL);
不少网站都是使用此函数作为通用的输入过滤函数,但是此函数默认情况是不过滤单引号的。这是非常非常地容易造成XSS漏洞。这样的做法和不过滤双引号没太大区别,只要前端写得稍微有点不规范(用了单引号)就会中招。下面这个示例改编自知乎梧桐雨的回答
' />
要求所有的时候都使用双引号不得使用单引号,这其实不太现实。所以,这个主要还是后端的责任,把单引号也要转义,我们用的时候一定要给这个函数加上参数 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() 출력을 사용할 때는 다음 사항을 확인하세요. 전달된 매개변수는 문자열입니다. 그렇지 않으면 평가 함수만큼 위험합니다.