PHP面试题

PHP知识

php反转字符串的三种方法

1、把分割字符串到一个数组中,然后遍历拼接:

<?php

function joinStrrev($str)
{
    if (strlen($str) <= 1) return $str;

    $newstr = '';
    //str_split(string,length) 函数把字符串分割到数组中:string 必需。规定要分割的字符串。length     可选。规定每个数组元素的长度。默认是 1。
    $strarr = str_split($str, 1);
    foreach ($strarr as $word) {
        $newstr = $word . $newstr;
    }

    return $newstr;
}

$str = "abcd";
$revstr = joinStrrev($str);
echo $revstr;

2、递归拼接

<?php

function recursionStrrev($str)
{
    if (strlen($str) <= 1) return $str;//递归出口

    $newstr = '';
    //递归点,substr(string,start,length) :substr() 函数返回字符串的一部分,如果 start 参数是负数且 length 小于或等于 start,则 length 为 0,正数 - 在字符串的指定位置开始,负数 - 在从字符串结尾的指定位置开始,0 - 在字符串中的第一个字符处开始
    $newstr .= substr($str, -1) . recursionStrrev(substr($str, 0, strlen($str) - 1));

    return $newstr;//递归出口
}

$str = "abcd";
$revstr = recursionStrrev($str);
echo $revstr;

3、php有自带的函数strrev

$str = 'abcd';
//第一种自带strrev实现翻转
echo strrev($str);

php7和php5的区别在于:

  • PHP7的性能是PHP5.0的两倍。
  • 与PHP5.0相比,PHP7.0去掉了一些旧的、不支持的SAPI(服务器端应用编程端口)和扩展。
  • 与PHP5.0相比,PHP7.0增加了空连接运算符。
  • 与PHP5.0相比,PHP7.0增加了一个组合比较运算符。
  • 与PHP5.0相比,PHP7.0增加了函数的返回类型声明。
  • 与PHP5.0相比,PHP7.0增加了标量类型声明。
  • PHP7.0在PHP5.0中增加了匿名类。

fastcgi和php-fpm

  • 什么是CGI
    CGI是为了保证Web Server传递过来的数据是标准格式的,方便CGI程序的编写者。

  • 什么是FASTCGI
    Fastcgi是CGI的升级版,一种语言无关的协议。

  • 什么php-fpm
    是一个实现了FastCGI(协议)的程序。
    php-fpm是一种master/worker多进程架构,master主要负责CGI及PHP环境初始化、事件监听、子进程状态等等, worker进程负责处理php请求。
    php-fpm实现了平滑启动(处理完的worker就重启)。
    PHP-FPM由1个master进程和N个worker进程组成。

  • 进程管理模式
    Static:静态模式, 启动是分配固定的进程, 后续不在动态增减worker的进程。
    Dynamic: 动态模式, 启动时分配固定的进程, 伴随着请求数的增加, 在设定的范围内动态调整worker进程。
    Ondemand: 按需分配, 当收到用户请求时fork worker进程。初始化时不生产worker进程, 当lister_socket收到request, 先检查是否存在已生成的空闲的worker进程, 诺存在则使用这个进程, 否则fork 一个新的进程, 每个一秒触发心跳事件, 会kill掉空闲超过设定时间的worker进程。

PHP生命周期

1. 模块初始化阶段(MINIT)

在这个阶段 PHP 首先检查 php.ini 文件中定义的扩展模块并对其进行初始化和加载工作,mysql、mbstring、json等等我们需要的功能扩展模块都会在这个阶段完成

2. 请求初始化阶段(RINIT)

初始化本次脚本请求所需要的变量以及变量值内容符号表,我们熟知的 、$_SESSION,$_COOKIE,$GLOBAL,$_GET,$_POST 等等超全局变量都会在这个阶段完成初始化的工作

3. 执行指定的 PHP 脚本程序
比如laravel框架处理一些http请求的处理逻辑

4. 请求处理完成阶段

这是第二个阶段的逆操作,在这个阶段,完成所有请求相关变量和符号表的清理工作,如 unset($_POST),然后按顺序调用扩展模块的 RSHUTDOWN 方法,通知扩展做好关闭前的准备工作。

5. 模块关闭阶段
这是阶段(1)的逆操作, PHP 调用每个扩展的 MSHUTDOWN 方法释放内存

Laravel生命周期

 1.使用Composer的自动加载功能,把所有需要使用的 PHP 文件添加到系统中以备调用
  require __DIR__.'/../vendor/autoload.php'; 

 2.创建 Laravel 单例应用实例
  $app = require_once __DIR__.'/../bootstrap/app.php';

 3.最关键的步骤,接受请求,对请求进行处理,返回请求处理的结果
  $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
  $response = $kernel->handle(
      $request = Illuminate\Http\Request::capture()
  );
  $response->send();

 4.请求结束,进行回调
  $kernel->terminate($request, $response);

猴子踢出圈编程,约瑟夫环问题(猴子选大王)

一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大王。

<?php
/*
1、一群猴子围在一起坐成环状(如:N=15)
2、从某个编号开始报数(如:K=9)
3、数到某个数(如:M=10)的时候,此猴出列,下一个猴子重新报数
4、一直循环,直到所有猴子出列,约瑟夫环结束,同时输出最后的大王。
910111213141512345678
3
45678910111213141512
13
141512456789101112
9
10111214151245678
*/

var_dump("最后的猴子大王是:" . monkeyKing(15, 10, 9));

function monkeyKing($n, $m, $k)
{
    if ($m > $n || $k > $n) {
        return 'm或k大于n,请重新输入';
    }
    //从第k个编号开始报数
    if($k>1){
    	//arr = [9,10,11,12,13,14,15,1,2,3,4,5,6,7,8];
        $arr = array_merge(range($k, $n), range(1, $k - 1));
    }else{
        $arr = range(1, $n);
    }

    //从第一个数开始数,数到第$m个开始剔除
    $i = 1;
    while (count($arr) > 1) { //如果数组长度大于1不断的进行循环,直到数组长度为1时跳出循环条件
        if ($i % $m == 0) {
            echo "删除数到的第【" . $m . "】个数,删除的数值为:" . $arr[$i - 1] . PHP_EOL;
        } else {
            //不被踢出的前面数将其则压入数组尾部
            $arr[] = $arr[$i - 1];
        }
        //将已经数过的数删除
        unset($arr[$i - 1]);
        //继续循环
        $i++;
//        var_dump(json_encode($arr));
//        sleep(1);
    }
    //返回当前数组的数值
    return current($arr);
}

在这里插入图片描述

php中重写父类方法时需要注意什么

php中重写父类方法时需要注意:
1、final关键字修饰的类方法不可被子类重写;
2、php是否重写父类方法只会根据方法名是否一致判断;
3、重写时访问级别只可以等于或者宽松于父类,不可提升访问级别。
a)父类为public 则子类重写也只能为public
b)父类为protected 则子类可为public/protected
c)父类为private 则子类public/protected/private皆可

获取字符串中出现次数最多的字符

解法一(考察基本功,得记住!)

<?php
$str = "ddfdadferaqwerwerrr";
//字符串分割成数组
$arr = str_split($str);
//格式['a'=>4,'r'=2]
$strCount = array_count_values($arr);
//对关联数组按照键【值】进行降序排序
arsort($strCount);
//获取第一个键
print_r(array_key_first($strCount));

解法二(对基本功和逻辑能力有一定要求)

<?php
$str = "ddfdadferaqwerwerrr";
//字符串分割成数组
$arr = str_split($str);
$con = array();
foreach ($arr as $value) {
    if (!@$con[$value]) {//如果新数组$con不存在该键则加入新数组并赋值为1
        @$con[$value] = 1;
    } else {//否则对应新数组$con在原来基础上累加值
        @$con[$value]++;
    }
}
//对关联数组按照键【值】进行降序排序
arsort($con);
//获取第一个键
print_r(array_key_first($con));

PHP 数组排序

sort() - 以升序对数组排序,对数组单元从低到高进行排序,数组单元经过排序后,键值重新分配
rsort() - 以降序对数组排序,对数组单元从高到底进行排序,数组单元经过排序后,键值重新分配
asort() - 根据值,以升序对关联数组进行排序,键值下标不变
ksort() - 根据键,以升序对关联数组进行排序,键值下标不变
arsort() - 根据值,以降序对关联数组进行排序,键值下标不变
krsort() - 根据键,以降序对关联数组进行排序,键值下标不变

三元运算与??区别

??并不等于三元运算符,相当于在三元运算时加入了isset()的比较运算

isset(参数)?1:0

写出空字符串""、null、空数组[]、空数组对象(object)[] 下分别在isset()、empty()函数下的结果

答:isset() 函数判断变量是否设置,empty() 函数判断变量是否为空

isset()测试结果:
$arr = "";
var_dump(isset($arr));	//返回bool值为true
-----------------------
$arr = null;
var_dump(isset($arr));	//返回bool值为false
-----------------------
$arr = [];
var_dump(isset($arr));	//返回bool值为true
-----------------------
$arr = (object)[];
var_dump(isset($arr));   //返回bool值为true
-----------------------

empty()测试结果:

var_dump(empty(""));	//空字符返回bool值为true
-----------------------

var_dump(empty(null));	//null返回bool值为true
-----------------------

var_dump(empty([]));	//空数组返回bool值为true
-----------------------

var_dump(empty((object)[]));   //空对象返回bool值为false
-----------------------

如何不使用第三个变量来交换两个数的值

题目:a=10,b=15,将a / b的值互换。
1) 算术运算
简单来说,就是通过普通的+和-运算来实现。代码如下:
int a,b;
a=10;b=12;
a=b-a; //a=2;b=12
b=b-a; //a=2;b=10
a=b+a; //a=10;b=10
通过以上运算,a和b中的值就进行了交换。表面上看起来很简单,但是不容易想到,尤其是在习惯标准算法之后。
它的原理是:把a、b看做数轴上的点,围绕两点间的距离来进行计算。
具体过程:第一句“a=b-a”求出ab两点的距离,并且将其保存在a中;第二句“b=b-a”求出a到原点的距离(b到原点的距离与ab两点距离之差),并且将其保存在b中;第三句“a=b+a”求出b到原点的距离(a到原点距离与ab两点距离之和),并且将其保存在a中。完成交换。
此算法与标准算法相比,多了三个计算的过程,但是没有借助临时变量。(以下称为算术算法)

该算法还可以这样做:

int a,b;

a=10;b=12;

a=a+b=22;

b=a-b=10;

a=a-b=12;

两个减操作一个加操作,执行的先后顺序不一样,其原理也稍微有些区别,但根本原理是一样滴。

逻辑题

1、公司有员工A、B、C三人,A员工花费10小时可以完成搬砖任务,B员工花费8小时可以办成搬砖任务,C员工花费7小时完成搬砖任务,现C员工已经搬砖2小时,问A、B员工合力完成剩余工作量需要多长时间
答:
将工作量看作1;
每小时完成工作量:A:1/10,B:1/8,C:1/7
剩余工作量:(1-1/7*2)
A、B员工合力每小时工作量:(1/10+1/8)
A、B员工合力完成剩余工作量需要时长:(1-1/7*2)/(1/10+1/8)

PHP正则匹配邮箱与手机号

正则匹配邮箱:

<?php
$mail = '11aaa@qq.com';  //邮箱地址
$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/";
preg_match($pattern, $mail, $matches);
var_dump($matches);  //输出匹配结果
?>

正则匹配手机号:
用正则匹配手机号码的时候, 我们先分析一下手机号码的规律:

  1. 手机号通常是11位的
  2. 经常是1开头
  3. 第二个数字通常是34578这几个数字, 2014.5.5日170号段的手机号开卖所以这里多了个7.
<?php
$str = '13712345678';
preg_match_all("/^1[34578]\d{9}$/", $str, $mobiles);
//var_dump($mobiles); 
include与required的区别

require()语句的功能与include()相类似,都是包括并运行指定文件。不同之处在于:对include()语句来说,在执行文件时每次都要进行读取和评估;而对于require()来说,文件只处理一次(实际上,文件内容替换require()语句)。这就意味着如果可能执行多次的代码,则使用require()效率比较高。另外一方面,如果每次执行代码时是读取不同的文件,或者有通过一组文件迭代的循环,就使用include()语句。
详细区别:
区别一、

include引入文件的时候,如果碰到错误,会给出提示,并继续运行下边的代码。
require引入文件的时候,如果碰到错误,会给出提示,并停止运行下边的代码。

区别二、

用法上却有一些不同,include()是有条件包含函数,而require()则是无条件包含函数。例如
if($something){
  require 'somefile.php';
}
这段代码中不论$something取何值,somefile.php都会被包含近文件,而如果使用include,则只有$something为真的时候才会包含文件somefile.php。

区别三、

include()执行时需要引用的文件每次都要进行读取和评估,require()执行时需要引用的文件只处理一次(实际上执行时需要引用的文件内容替换了require()语句)可以看出若有包含这些指令之一的代码和可能执行多次的代码,则使用require()效率比较高,若每次执行代码时相读取不同的文件或者有通过一组文件叠代的循环,就使用include(),可以给想要包括的文件名设置变量,当参数为 include()时使用这个变量。

PHP中define和defined的区别

对于初学者会混淆这两个函数

1.define用来定义一个常量,常量也是全局范围的。不用管作用域就可以在脚本的任何地方访问

常量。一个常量一旦被定义,就不能再改变或者取消定义

如:

define("path","mlx1036@163.com")  define为常mlx1036@163.com

为常量的值

2.defined用来检测常量有没有被定义,若常量存在,则返回 true,否则返回 false如:

if(defined("path")){

echo "true";

   }else{

     echo "false";

}
PHP中传值与传引用的区别是什么

传值是指将参数的值复制到一个新的变量中,然后将这个变量传递给函数。在函数内部,对这个变量所做的任何更改都不会影响原始变量的值。这意味着传值方式不会改变原始变量的值。

下面是传值的示例:

<?php
function addOne($num) {
    $num++;
    return $num;
}

$num = 5;
$newNum = addOne($num);

echo $num;     // 输出 5
echo $newNum;  // 输出 6

传引用是指将参数的引用(即内存地址)传递给函数。这意味着在函数内部对参数的任何更改都会反映在原始变量中。

下面是传引用的示例:

<?php
function addOne(&$num) {
    $num++;
}

$num = 5;
addOne($num);

echo $num;  // 输出 6

可以看到,传值方式不会更改原始变量的值,而传引用方式会更改原始变量的值。因此,在选择使用哪种参数传递方式时,需要根据具体情况考虑是否需要更改原始变量的值。

支持回调数组函数array_map()

array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。
回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。

语法:

array_map(myfunction,array1,array2,array3...)

例子:

<?php
function myfunction($v1,$v2)
{
if ($v1===$v2)
  {
  return "same";
  }
return "different";
}

$a1=array("Horse","Dog","Cat");
$a2=array("Cow","Dog","Rat");
print_r(array_map("myfunction",$a1,$a2));
?>

php中array_merg与数组相加+合并有什么区别?

1)键名为数字时,array_merge()不会覆盖掉原来的值,但+合并数组则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉(不是覆盖)

需要注意的是数组键形式 ‘数字’ 等价于 数字

例子:

<?php
$a = array('a','b');
$b = array('c', 'd','c');
#或者以下数字关联的数组与字符串的数字形式的返回结果是一样的
//$a = array(0 => 'a', 1 => 'b');
//$b = array('0' => 'c', '1' => 'd');

$c = $a + $b;

var_dump($c);
echo "<pre>";
var_dump(array_merge($a, $b));


结果:
array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> string(1) "c" }
array(5) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
  [3]=>
  string(1) "d"
  [4]=>
  string(1) "c"
}

2)键名为字符时,+仍然把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉,但array_merge()此时会覆盖掉前面相同键名的值

<?php
$a = array('a' => '11', 'b' => '22');
$b = array('a' => '33', 'b' => '44','c'=>'ccc');

$c = $a + $b;

var_dump($c);
echo "<pre>";
var_dump(array_merge($a, $b));

结果:
array(3) { ["a"]=> string(2) "11" ["b"]=> string(2) "22" ["c"]=> string(3) "ccc" }
array(3) {
  ["a"]=>
  string(2) "33"
  ["b"]=>
  string(2) "44"
  ["c"]=>
  string(3) "ccc"
}

数组去除空与去重,考察数组函数的使用,并重新组装新数组

<?php
#数组去除空与去重,考察数组函数的使用,并重新组装数组
$arr = [0 => 'name', 1 => '', 2 => 'age', 3 => 'name'];
#数组去空
$arr1 = array_filter($arr);
#数组去重
$arr2 = array_unique($arr1);
#数组排序
$arr3 = []; #必须先声明
foreach ($arr2 as $value){
    $arr3[] = $value;
}
var_dump($arr3);

写一段PHP demo代码实现简单单例模式

<?php

class HttpClient
{
    #1、创建一个静态私有变量存放实例化对象
    private static $instance;
    #2、创建一个私有构造函数
    private function __contruct()
    {

    }
    #3、防止外部克隆该类
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }
    #4、防止序列化
    private function __wakeup()
    {

    }
    #5、提供唯一静态入口
    public static function getInstance()
    {
        if(!(static::$instance instanceof static)){
            static::$instance = new static;
        }
        return static::$instance;
    }
}

$obj1 = HttpClient::getInstance();
$obj2 = HttpClient::getInstance();
var_dump($obj1 === $obj2);

PHP关键字

  • this
    当一个方法在类定义内部被调用时,有一个可用的伪变量 this。this 是一个到当前对象的引用
  • parent
    本质上就是代表父类这个“类”,而不是父类的“对象”
  • static
    声明类属性或方法为静态,就可以不实例化类而直接访问。静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
  • self
    静态成员函数内不能用this调用非成员函数,但可以用self调用静态成员函数/变量/常量
    其他成员函数可以用self调用静态成员函数以及非静态成员函数
    self就是写在哪个类里面, 实际调用的就是这个类.
    static代表使用的这个类, 就是你在父类里写的static,然后被子类覆盖,使用的就是子类的方法或属性
  • instanceof
    用于确定一个 PHP 变量是否属于某一类 或者其子类的示例
  • const
    一个常量一旦被定义,就不能再改变或者取消定义
    不能在函数内,循环内以及 if 或 try/catch 语句之内用 const 来定义常量
    使用 const 关键字定义的常量总是大小写敏感的,而使用 define()不区分大小写。
  • final
    如果父类中的方法被声明为final, 则子类无法覆盖该方法
    如果一个类被声明为final, 则不能被继承
    属性不能被定义为 final,只有类和方法才能被定义为 final
  • clone
    因为 clone 的方式实际上是对整个对象的内存区域进行了一次复制并用新的对象变量指向新的内存,因此赋值后的对象和原对象之间是相互独立,并且调用对象的__clone(), 当对象被复制后,PHP 5 会对对象的所有属性执行一个浅复制(shallow copy)

递归删除目录中所有文件

//递归删除目录中所有文件
function delFileByDir($dir) {
    $dh = opendir($dir);//打开目录句柄
    while ($file = readdir($dh)) {//读取路径
       if ($file != "." && $file != "..") {//过滤点
 
          $fullpath = $dir . "/" . $file;//拼装路径
          if (is_dir($fullpath)) {//判断拼装的路径是否为目录,是则进入该目录,不是则删除该文件
             delFileByDir($fullpath);//递归进入该目录
          } else {
             unlink($fullpath);//删除该文件
          }
       }
    }
    closedir($dh);//关闭目录句柄
 }

数据库知识

mysql统计订单orders表用户1月销售量,返回前三名用户,字段id,user_id,create_time

SELECT user_id, COUNT(*) as sales_count
FROM orders
WHERE MONTH(create_time) = 1
GROUP BY user_id
ORDER BY sales_count DESC
LIMIT 3;

数据库三范式

1、表的设计一般要符合三范式(3NF)
2、1NF,原子性,不可分割(理解:字段不可分割)
3、2NF,唯一性,在1NF基础上的限制(理解:建立主键)
4、3NF,冗余性约束(理解:建立外键)

什么是事务?及其特性?

事务:是一系列的数据库操作,是数据库应用的基本逻辑单位

特性:
(1)原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。

(2)一致性或可串性。事务的执行使得数据库从一种正确状态转换成另一种正确状态

(3)隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,

(4) 持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。

简单理解:在事务里的操作,要么全部成功,要么全部失败。

事务隔离级别(MVCC 多版本并发控制)

在数据库并发无锁情况下,数据库对并发的处理情况如下

  • Read Uncommitted-读未提交
    特点:
    一个事务在处理过程中读取了另外一个事务未提交的数据
  • 读提交(Read Committed)
    特点:
    读取的数据是其它事务提交后的数据, 在同一事务过程中,多次读取到的数据是不一致的
  • 可重复读(Repeatable Read)
    特点:
    1)在同一事务中,每次读取的数据是一致的
    2)REPEATABLE READ是不能防止幻读产生的。INNODB使用了next-key locks实现了防止幻读的发生。
    3)RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。
  • 串行化
    特点:各事务间互斥。即使是读操作也会互斥。所有的读都是当前读, 都加锁。

SQL题

一、如下表展示了部分学生的各科目学习成绩信息,请写出sql语句找出所有科目平均分大于60分的学生ID:

Idstudent_idcourse_idscore
12189
24256
36191
44380
52161

答:所有科目 group by ,然后从新表中过滤,平均分>60的数据
select * from (select student_id,format(avg(score),2)as avg_score from info group by student_id) as info_back where avg_score > 60

二、从mysql数据库删除重复记录只保留其中一条
答:
1、要删除重复的记录,就要先查出重复的记录,这个很容易做到
select * from cqssc group by expect having count(expect) > 1
2、Mysql中是不能删除查询出来的记录的,这里很容易错,而是要通过一张临时表来解决
delete from cqssc where id in (select id from (select id from cqssc where expect in (select expect from cqssc group by expect having count(expect)>1) and id not in (select min(id) from cqssc group by expect having count(expect)>1)) as tmpresult)

缓存知识

Redis为什么这么快

  • 读写全部在内存
    Redis最大的特点在数据数据的读写全部在内存中进行, 进而带来了极大的效率优势
  • 单线程处理请求
    由于Redis都是在内存里面进行读写的, 如果使用多线程对数据进行读写, 那么同时就会带来锁开销, 大量写入的情况下, 过多的锁带来的时间消耗比多线程带来的多核利用优势更大
  • I/O多路复用技术
    I/O多路复用我们又称之为事件驱动,Redis基于epoll等技术实现了网络部分响应的同步非阻塞I/O模式

Redis缓存穿透、击穿、雪崩

  • 穿透:
    理解:恶意用户故意访问redis和mysql中不存在的数据
    解决:做数据过滤或者hash存储数据是否存在(布隆过滤器 key=null)
  • 击穿:
    理解:大量的请求同时访问同一条数据, 刚好这条数据缓存过期, 导致所有的请求都到数据库(热点过期、从没被缓存过)
    解决:可以互斥锁, 当缓存不存在的时候, 只有一个请求去生成缓存
  • 雪崩:
    理解:某一时刻大量的缓存数据同时失效, 导致大量的请求打到数据库上
    解决:避免缓存集中失效, 不同的key设置不同的时间

HTTP协议

常见的 web 攻击方式与解决方案

常见攻击

XSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往 Web 页面里插入恶意 html 代码,当用户浏览该页之时,嵌入的恶意 html 代码会被执行,从而达到恶意用户的特殊 目的。

XSS 属于被动式的攻击,因为其被动且不好利用,所以许多人常呼略其危害性。但是随着前端技术的不断进步富客户端的应用越来越多,这方面的问题越来 越受关注。

举个简单例子 :

假如你现在是 sns 站点上一个用户,发布信息的功能存在漏洞可以执行 js 你在 此刻输入一个 恶意脚本,那么当前所有看到你新信息的人的浏览器都会执行这个脚本弹出提示框 (很爽吧 弹出广告 :)),如果你做一些更为激进行为呢 后果难以想象。

解决方案:
过滤特殊字符

CSRF (Cross Site Request Forgery),跨站点伪造请求。顾名思义就是 通过伪造连接请求在用户不知情的情况下,让用户以自己的身份来完成攻击者需要达到的一些目的。csrf 的攻击不同于 xss csrf 需要被攻击者的主动行为触发。这样听来似乎是有 “被钓鱼” 的嫌疑。

多窗口浏览器这这方面似乎是有助纣为虐的嫌疑,因为打开的新窗口是具有当前所有 会话的,如果是单浏览器窗口类似 ie6 就不会存在这样的问题,因为每个窗口都是一个独立的进程。

举个简单例子 : 你正在玩白社会, 看到有人发了一个连接,你点击过去,然后这个连接里面伪造了一个送礼物的表单,这仅仅是一个简单的例子,问题可见一般。

cookie 劫持。通过获取页面的权限,在页面中写一个简单的到恶意站点的请 求,并携带用户的 cookie 获取 cookie 后通过 cookie 就可以直以被盗用户的身份登录站点。这就是 cookie 劫持。

举个简单例子: 某人写了一篇很有意思的日志,然后分享给大家,很多人都点击查看并且分享了该日志,一切似乎都很正常,然而写日志的人却另有用心,在日志中偷偷隐藏了一个 对站外的请求,那么所有看过这片日志的人都会在不知情的情况下把自己的 cookie 发送给了 某人,那么他可以通过任意一个人的 cookie 来登录这个人的账户。

解决方案:
请求地址中添加 token 并验证

SQL 注入攻击

在 SQL 注入攻击 中,用户通过操纵表单或 GET 查询字符串,将信息添加到数据库查询中。

DNS 攻击

拒绝服务攻击

拒绝服务攻击即攻击者想办法让目标机器停止提供服务,是黑客常用的攻击手段之。

攻击者进行拒绝服务攻击,实际上让服务器实现两种效果:一是迫使服务器的缓冲区满,不接收新的请求;二是使用 IP 欺骗,迫使服务器把合法用户的连接复位,影响合法用户的连接

TCP、UDP、HTTP、HTTPS、之间的区别

网络七层模型由下往上分为:
物理层 —

数据链路层 —

网络层 –  IP协议

传输层 –  TCP协议

会话层 –

表示层和应用层 –  HTTP与HTTPS协议
在这里插入图片描述
1、TCP/IP连接

TCP传输控制协议,是一种提供可靠数据传输的通用协议

手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端机通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。

建立起一个TCP连接需要经过“三次握手”:
 
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
 
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
 
第三次握手:客户端收到服务器的SYNACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

2、UDP协议
UDP 用户数据报协议,是一个面向无连接的协议。采用该协议不需要两个应用程序先建立连接。UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性差。
(1)、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
(2)、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3、HTTP

  1. http是一个简单的请求-响应协议,它通常运行在TCP之上。
  2. 它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。
  3. 请求和响应消息的头以ASCII码形式给出;而消息内容则具有一个类似MIME的格式。
  4. 这个简单模型是早期Web成功的有功之臣,因为它使得开发和部署是那么的直截了当。

4、https

HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
https协议需要到ca申请证书,一般免费证书很少,需要交费。http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。

5、SOCKET

1)SOCKET连接与TCP/IP连接

创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

2)Socket连接与HTTP连接

由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值