PHP面试(三)
XSS攻击是什么
XSS
常见的 XSS 输入
XSS 输入通常包含 JavaScript 脚本,如弹出恶意警告框:<script>alert("XSS");</script>
XSS 输入也可能是 HTML 代码段,譬如:
网页不停地刷新** <meta http-equiv="refresh" content="0;">**
嵌入其它网站的链接 <iframe src=http://xxxx width=250 height=250></iframe>
如何预防XSS
目前防御XSS的方式:
PHP 提供了htmlspecialchars()函数可以将 HTML 特殊字符转化成在网页上显示的字符实体编码。这样即使用户输入了各种 HTML 标记,在读回到浏览器时,会直接显示这些 HTML 标记,而不是解释执行。htmlspecialchars()函数可以将以下五种 HTML 特殊字符转成字符实体编码:
- &转成 &
- “转成 "
- <转成 <
- ·>转成 & g t;
- ‘转成 '
当直接调用 htmlspecialchars($str)时, & " < > 被转义。
当设置 ENT_QUOTES 标记时, 即调用htmlspecialchars($str, ENT_QUOTES)时,单引号也被转义。
当设置 ENT_NOQUOTES 标记时,单引号和双引号都不会被转义。即调用 htmlspecialchars($str, ENT_NOQUOTES)时,只有& < > 被转义。
<?php
if (isset($_POST['name'])){
$str = trim($_POST['name']); //清理空格
$str = strip_tags($str); //过滤html标签
$str = **htmlspecialchars**($str); //将字符内容转化为html实体
$str = addslashes($str);
echo $str;
}
?>
<form method="post" action="">
<input name="name" type="text">
<input type="submit" value="提交" >
</form>
PHP 提供了strpos()、strstr()、preg_match()等函数可用于检测非法字符和字符串;preg_replace() 函数可用于替换非法字符串。
CRSF(Cross-site request forgery),中文名称:跨站请求伪造
那么CSRF到底能够干嘛呢?你可以这样简单的理解:攻击者可以盗用你的登陆信息,以你的身份模拟发送各种请求。攻击者只要借助少许的社会工程学的诡计,例如通过QQ等聊天软件发送的链接(有些还伪装成短域名,用户无法分辨),攻击者就能迫使Web应用的用户去执行攻击者预设的操作。例如,当用户登录网络银行去查看其存款余额,在他没有退出时,就点击了一个QQ好友发来的链接,那么该用户银行帐户中的资金就有可能被转移到攻击者指定的帐户中。
所以遇到CSRF攻击时,将对终端用户的数据和操作指令构成严重的威胁;当受攻击的终端用户具有管理员帐户的时候,CSRF攻击将危及整个Web应用程序。
image.png从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤 :
-
登录受信任网站A,并在本地生成Cookie 。
-
在不退出A的情况下,访问危险网站B。
看到这里,读者也许会问:“如果我不满足以上两个条件中的任意一个,就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站,特别现在浏览器都是支持多tab的。
你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。
上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
因此对于用户来说很难避免在登陆一个网站之后不点击一些链接进行其他操作,所以随时可能成为CSRF的受害者。
CSRF攻击主要是因为Web的隐式身份验证机制,Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。
服务端的预防CSRF攻击的方式方法有多种,但思想上都是差不多的,主要从以下2个方面入手:
-
正确使用GET,POST和Cookie;
-
在非GET请求中增加伪随机数;
一般而言,普通的Web应用都是以GET、POST为主,还有一种请求是Cookie方式。我们一般都是按照如下方式设计应用:
-
GET常用在查看,列举,展示等不需要改变资源属性的时候;
-
POST常用在下达订单,改变一个资源的属性或者做其他一些事情;
接下来我就以Java语言来举例说明,如何限制对资源的访问方法:
Blade.regRoute("/user/:uid", IndexRoute.class, "getuser", HttpMethod.GET);
Blade.regRoute("/user/:uid", IndexRoute.class, "modifyuser", HttpMethod.POST);
代码是blade框架的写法。
这样处理后,因为我们限定了修改只能使用POST,当GET方式请求时就拒绝响应,所以上面图示中GET方式的CSRF攻击就可以防止了,但这样就能全部解决问题了吗?当然不是,因为POST也是可以模拟的。
因此我们需要实施第二步,在非GET方式的请求中增加随机数,这个大概有三种方式来进行:
为每个用户生成一个唯一的cookie token,所有表单都包含同一个伪随机值,这种方案最简单,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败,但是由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,所以这个方案必须要在没有XSS的情况下才安全。
每个请求使用验证码,这个方案是完美的,因为要多次输入验证码,所以用户友好性很差,所以不适合实际运用。
不同的表单包含一个不同的伪随机值
一次完整的网络请求
一次完整的网络请求.pngPCNTL
PHP使用PCNTL系列的函数也能做到多进程处理一个事务。比如我需要从数据库中获取80w条的数据,再做一系列后续的处理,这个时候,用单进程?你可以等到明年今天了。。。所以应该使用pcntl函数了。
假设我想要启动20个进程,将1-80w的数据分成20份来做,主进程等待所有子进程都结束了才退出:
$max = 800000;
$workers = 20;
$pids = array();
for($i = 0; $i < $workers; $i++){
$pids[$i] = pcntl_fork();
switch ($pids[$i]) {
case -1:
echo "fork error : {$i} \r\n";
exit;
case 0:
$param = array(
'lastid' => $max / $workers * $i,
'maxid' => $max / $workers * ($i+1),
);
$this->executeWorker($input, $output, $param);
exit;
default:
break;
}
}
foreach ($pids as $i => $pid) {
if($pid) {
pcntl_waitpid($pid, $status);
}
}
这里当pcntl_fork出来以后,会返回一个pid值,这个pid在子进程中看是0,在父进程中看是子进程的pid(>0),如果pid为-1说明fork出错了。
使用一个$pids数组就可以让主进程等候所有进程完结之后再结束了
PHP socket
Socket是什么
socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
以上内容来自百度百科
简单说来,socket可以帮助不同的服务在不同的端口进行通信。
PHP curl
cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议和选项,如HTTP、FTP、TELNET等,能提供 URL 请求相关的各种细节信息。最爽的是,PHP 也支持 cURL 库。
数组函数array_merge和+的区别:
$a=array('a'=>1,'b'=>2,'c'=>3);
$b=array('b'=>5,'c'=>6,'d'=>7);
print_r(array_merge($a,$b));
print_r($a+$b);
就输出:
array(
[a]=>1
[b]=>5
[c]=>6
[d]=>7
)
array
(
[a]=>1
[b]=>2
[c]=>3
[d]=>7
)
array_merge()
如果输入的数组中有相同的字符串键名,则该键名后面的值将覆盖前一个值。对于使用+合并数组
如果数组中有相同的字符串键名(不管是不是数字),则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值抛弃掉 。
isset如果变量存在(非NULL)则返回TRUE,否则返回FALSE.变量设置为NULL,返回也是FALSE.PHP的isset()函数 一般用来检测变量是否设置
empty.如果变量时非空和非零的值,则empty返回FALSE,换句话说,NULL,FALSE,0,$var未定义。以及没有属性的对象都被认为是空的。如果var为空,则返回true。**PHP的empty()函数 判断值为否为空 **
TCP和UDP的区别
TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。
UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。
数据库的事务:
- 事务具有原子性,就是把多个数据库操作合并成一个操作,让它具有原子性,有一个操作失败会回滚。(多个操作,会有出错的,有一个失败的话,整个操作会回滚。)
2。 可移植性
会把自己操作过的数据设置一个所,在这个数据没有结束之前,其他人都不能操作这个数据。
两个数据库的操作
两个数据库需要两次链接
两次都需要启动事务,每个事务都成功之后,在提交。
A数据库 执行两条语句,成功
B数据库 执行三条语句,成功
之后再提交。
索引的作用
从数据结构角度想:B+树。
存在叶子节点上面的是数据,innodb。
存在叶子结点上面的是物理地址,MYiSAM.
对于这种自己不会的问题,引导到自己会的问题上面。
连表查询和嵌套查询的那个效率更高:
如果自己不知道哪一个效率高,这个应该考虑的是优化的问题,你可以说,我还没有做过实验,但是可以用explain做一下实践。
优化就是sql的关键点。
哪种效率最高,哪种最优。
- 谁用了索引,数取数据的行数少,谁的效率就搞,它就好。不管它是group by, order, join.