php session应用与安全问题解决办法

 更新时间:2016年11月25日 15:51  点击:1579

当然使用 Session 还有很多优点,比如控制容易,可以按照用户自定义存储等(存储于数据库教程)。我这里就不多说了。

  Session 在 php教程.ini 是否需要设置呢?一般不需要的,因为并不是每个人都有修改 php.ini 的权限,默认 Session 的存放路径是服务器的系统临时文件夹,我们可以自定义存放在自己的文件夹里,这个稍后我会介绍。

  开始介绍如何创建 Session。非常简单,真的。

  启动 Session 会话,并创建一个 $admin 变量:

// 启动 Session
session_start();
// 声明一个名为 admin 的变量,并赋空值。
$_SESSION["admin"] = null;
?>

  如果你使用了 Seesion,或者该 PHP 文件要调用 Session 变量,那么就必须在调用 Session 之前启动它,使用 session_start() 函数。其它都不需要你设置了,PHP 自动完成 Session 文件的创建。

  执行完这个程序后,我们可以到系统临时文件夹找到这个 Session 文件,一般文件名形如:sess_4c83638b3b0dbf65583181c2f89168ec,后面是 32 位编码后的随机字符串

,函数bool session_set_save_handler ( callback open, callback close, callback read, callback write, callback destroy, callback gc )就是提供给我们解决这个问题的方案.
该函数使用的6个函数如下:
1. bool open() 用来打开会话存储机制,
2. bool close() 关闭会话存储操作.
3. mixde read() 从存储中装在session数据时使用这个函数
4. bool write() 将给定session ID的所有数据写到存储中
5. bool destroy() 破坏与指定的会话ID相关联的数据
6. bool gc() 对存储系统中的数据进行垃圾收集
例子见php手册session_set_save_handler() 函数.
如果用类来处理,用

 

session_set_save_handler(
array('className','open'),
array('className','close'),
array('className','read'),
array('className','write'),
array('className','destroy'),
array('className','gc'),
)

关于session安全问题
攻击者通过投入很大的精力尝试获得现有用户的有效会话ID,有了会话id,他们就有可能能够在系统中拥有与此用户相同的能力.
http协议时无状态的,所以通常网站都会用session来标示一个用户。session在客户端就是一个保存一个特殊令牌的cookie,关键的信息是存放在服务器端的。但因为令牌是保存在客户端,并且要经过传输,所以还是很不安全的。

1、会话终止,但令牌仍处于活动状态

情景: 当用户退出时,程序只是删除了令牌(例如,通过发布一个清空令牌的Set-Cookie指令)。然而并没有删除服务器端的数据,如果用户继续使用该令牌,仍然可以使用。
解决方法:退出后删除服务器端的数据。
测试方法:退出后,仍然使用该令牌,如果活动正常,这该令牌仍然有效。(使用Firefox的web developer 插件就可以)

2、令牌可以通过url传输

情景:如果可以通过url传输,攻击者使用攻击者站点上的链接,可以轻松的固定受害人的会话标识符,比如:http://www.example.com/index.php?PHPSESSID=fixed_session_id。假使受害者还没有一个example.com站点会话标识符的cookie,那么会话固定就成功了。一旦受害者使用了攻击者指定的会话标识符,那么攻击者就能劫持受害者的会话,并模仿受害者的用户代理,试图假装成受害者。
解决方法:在PHP中设置 use_only_cookies  的值 1 , 在php中默认就是 1,可以不修改。

3、在网络上泄露了令牌

情景:网络以非加密方式传输会话令牌,则处在适当位置的监听者可以截取此令牌。
a、当用户登录时是使用http非安全通道时,用户与服务器间传输的所有的数据都是可以截获的。 这时登录者对于监听者是没有什么秘密可言的。这时候,如果截获的数据不足以执行第二次登录  (例如,一些银行系统会要求登录者提交不断变化的验证码)。如果攻击者想执行任何操作,就必须劫持他窃听的会话。

b、一些程序在一些HTTP页面就发送一个令牌,然后再登录页面开始使用https教程,并且登录时也不修改此令牌,结果最初并未通过验证的用户会话在登录后被升级为通过验证的会话。窃听者可以在登录前就拦截到这个令牌。所以为了提高安全性,程序可以在登录的时候发送令牌或发送一个新令牌。

c、程序容许通过HTTP登录,如果攻击者成功将用户的链接降级为HTTP,他仍然能够拦截这个令牌。

d、如果所有的页面都是用HTTPS,但图片和一些js,css教程等的静态文件是使用HTTP传输。这时如果静态文件和登录等页面时在同一个域下,令牌也会通过HTTP泄露。所以将静态文件使用别的域好处是很多的。
其他解决方法:
a、如果应用程序使用HTTP Cookie传送会话令牌,应确认其设置了secure标记,防止他们通过非加密链接传送令牌。
b、不接受非安全登录
c、session和客户端的HTTP_USER_AGENT绑定,但该方法效果不是很理想,攻击者可以伪造这些数据。

4、客户端令牌易被劫持

a、网站存在跨站攻击漏洞,这样用户的令牌很容易被劫持。需要检查全站,避免出现跨站攻击,也可以设置cookie_httponly,可以在一定程度上避免脚本的攻击。具体可以参考  利用httponly提升应用程序安全性 

b、攻击者可以使用其他针对用户的攻击,以不同的方式劫持用户的会话。包括实施会话固定攻击,即攻击者向一名用户发送一个已知的会话令牌,等待他们登录。
解决方法:1、可以每次登录成功后发送新的会话令牌
2、对令牌设定一个特别的格式,不接受其他格式的令牌,该方法效果并不是很好。


5、Cookie范围过于宽泛

浏览器在提交Cookie时会将Cookie提交到设定的域及其任何子域,而不提交到其他域。如果应用程序将Cookie的域设定的过于宽泛,会是程序出现各种漏洞。


6、令牌不够强大


令牌在其生成过程中,过于简单,或者有规律可循,从而使攻击者可以以常规方式预测或推断其他用户的令牌。例如,攻击者可以在A时间得到从网站正常获取一个令牌,在B时间在网站获取一个令牌,则通过分析,得到这个时间段的大量令牌样本,从而攻击。


解决方法:生成一个强大的令牌,得到足够的复杂度。但一些高强度的随机源必须采用足够的步骤获得足够的熵,这需要时间,所以通常不能满足需求。所以可以通过合并一些用户特有的数据来得到足够的熵。可以使用的数据:
1、一串随机数
2、来源IP地址
3、请求中的User_Agent消息头
4、请求时间
5、服务器私密的随机数
串联上面的数据,然后使用适当的散列算法(比如md5,SHA-256)等等对这个字符串处理。(将最容易变化的数据项放在散列输入的开始部分有助于最大化散列算法中的“雪崩”效应。


其他的一些增强安全的方法:

1、每页面令牌
在每个页面使用新的令牌,可以通过HTML表单传送,也可以使用Cookie传送,如果出现不匹配的情况整个会话终止。

2、在执行重要操作前,要求进行两步确认操作

安全是个大问题,细节方面是最重要的。这篇文章是我在阅读《黑客攻防技术宝典-web实战篇》记下的笔记。
--冷锋

<?php
if(!isset($_SESSION['user_agent'])){
$_SESSION['user_agent'] =$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'];
}
/* 如果用户session ID是伪造 */
elseif ($_SESSION['user_agent'] != $_SERVER['REMOTE_ADDR'] .$_SERVER['HTTP_USER_AGENT']) {
session_regenerate_id();
}
?>

PHP中那么多排序函数还自己写这个干吗?!后来想想,原来我错了,编程并不是死记硬背的机械运动,更是多种思维的集合;经常练习算法的目的就是扩展自己思维的目的。

  遂自己也试着写了写……
<?php教程
$array = array(10,5,36,86,2,56,9,15,8,4,3,41);
$num = count($array);
for($i = 0;$i<$num-1;$i++){
for($j = $i+1;$j<$num;$j++){
if($array[$j]>$array[$i]){//这里交换数组的值
$temp = $array[$i];
$array[$i] = $array[$j];
$array[$j] =$temp;
}
}
}
print_r($array);
?>
  这是写的冒泡排序算法,结果还是可以的:
---------- PHP Debug ----------
Array
(
[0] => 86
[1] => 56
[2] => 41
[3] => 36
[4] => 15
[5] => 10
[6] => 9
[7] => 8
[8] => 5
[9] => 4
[10] => 3
[11] => 2
)

输出完成 (耗时 0 秒) - 正常终止
  看着有了成功的小喜悦,就又写了一个,于是问题就出来了——
<?php
$array = array(10,5,36,86,2,56,9,15,8,4,3,41);
$num = count($array);
for($i=0;$i<$num-1;$i++){
for($j=$i+1;$j<$num;$j++){
if($array[$j]>$array[$i]){//这里是交换键值
$temp = $i;
$i=$j;
$j=$temp;
}
}
}
print_r($array);
?>
  结果惨不忍睹啊……
---------- PHP Debug ----------
Array
(
[0] => 10
[1] => 5
[2] => 36
[3] => 86
[4] => 2
[5] => 56
[6] => 9
[7] => 15
[8] => 8
[9] => 4
[10] => 3
[11] => 41
)

输出完成 (耗时 0 秒) - 正常终止

php教程三种常用的排序算法

1、冒泡排序(稳定排序)

个人理解:冒泡排序就是两个循环,大循环套小循环,从头或者尾部开始比较连续的两个元素的大小,如果不符合自己的排序标准(由小到大,或由大到小),则交换其值。

<?php
$arr=array(10,15,16,18,20,3,9,7,18,99);
for($i=1;$i<=9;$i++)
   for($j=1;$j<=10-$i;$j++)
      if($arr[$j-1]>$arr[$j])
      {$temp=$arr[$j-1];$arr[$j-1]=$arr[$j];$arr[$j]=$temp;}
      echo"after sorted:";
   for($i=0;$i<=9;$i++)
      echo $arr[$i].",";
     
 ?>

方法二

function bubble_sort($array){

  $count=count($array);

  for($i=0;$i<$count;$i++){

    for($j=$count-1;$j>$i;$j--){

      if($array[$j]<$array[$j-1]){//如果后面的值小于前面的元素,则交换值

        $temp=$array[$j];

        $array[$j]=$array[$j-1];

        $array[$j-1]=$temp;

      }

    }

  }

}

2、快速排序(又称数组排序)(不稳定排序)

个人理解:在要排序的数组中找一个关键数据(标准值),通常把数组的第一个元素当成关键数据,然后循环数组,从第二个元素开始依次将元素值与关键数据进行比较,如果小于关键数据,就把该元素放在关键值左边,如果答应关键数据,就把该元素放在关键数据右边,将关键值左边元素存成数组,右边元素也存成数组,再分别进行以上排序,得到的数组与关键数据合并数组后就排序成功

function quick_sort($array){

  $count=count($array);

  if($count<=1) retrun $array;  //如果数组只有一个元素或为空,则直接返回数组,不用排序了

  $key=$array[0]; //将数组第一个元素设置为关键数据

  $left_arr=array();

  $right_ar=array();

  for($i=1;$i<$count;$i++){

    if($array[$i]<=$key)

      $left_arr[]=$array[$i];

    else

      $right_arr[]=$array[$i];

  }

  $left_arr=quick_sort($left_arr);

  $right_arr=quick_sort($right_arr);

  //返回合并后的数组

  return array_merge($left_arr,array($key),$right_arr);

}

3、选择排序(不稳定排序)

个人理解:选择排序就是在要排序的数组中选出最小值与第一个元素交换值,然后再剩下的元素中选出最小值与第二个元素交换值,如此循环到倒数第二个元素和最后一个元素比较为止。

function select_sort($array){

  $count=count($array);

  if($count<=1) return $array;

  for($i=0;$i<$count-1;$i++){

    $min=$array[$i]; //假设当前元素为数最小,比较后再调整

    for($j=$i+1;$j<$count;$j++){

      if($array[$j]<$min){

        $min=$array[$j];

        $key=$j; //将此时值最小的元素的键名记下,

      }

    }

    if($min!=$array[$i]){ //如果min在循环中改变了,就需要交换数据

      $temp=$array[$i];

      $array[$i]=$array[$key];

      $array[$key]=$temp;

    }

  }

}

 

今天使用POST方式(GET方式也要注意)向PHP提交了一个JSON数据,比如:

{"a":1,"b":2}

在PHP中取出这个数据:

$s=$_POST['data'] ;//or $_GET['data']

然后这个串取出后是被转义的:

 {"a":1,"b":2}

如果直接调用:

$obj = json_decode($s); 

print_r($obj); 
echo $obj->a;
 是错误的,会报告错误.

如果$s直接定义:

$s='{"a":1,"b":2}';

则没有问题.

所以在PHP中处理JSON时需要进行一下转义处理:

$s=strips教程lashes($_POST['data']) ;

这样再进行json解码就可以了.


json_decode — 对 JSON 格式的字符串进行编码
json_encode — 对变量进行 JSON 编码

Report a bug 说明
string json_encode ( mixed $value )
返回 value 值的 JSON 形式

Report a bug 参数

value
待编码的 value ,除了resource 类型之外,可以为任何数据类型

该函数只能接受 UTF-8 编码的数据(译注:指字符/字符串类型的数据)


Report a bug 返回值
编码成功则返回一个以 JSON 形式表示的 string 。

Report a bug 范例

Example #1 A json_encode() 的例子

<?php教程
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);

echo json_encode($arr);
?>
以上例程会输出:

{"a":1,"b":2,"c":3,"d":4,"e":5}

 

json_encode — 对变量进行 JSON 编码

json_decode — 对 JSON 格式的字符串进行编码

Report a bug 说明
mixed json_decode ( string $json [, bool $assoc ] )
接受一个 JSON 格式的字符串并且把它转换为 PHP 变量

Report a bug 参数

json
待解码的 json string 格式的字符串。

assoc
当该参数为 TRUE 时,将返回 array 而非 object 。


Report a bug 返回值
Returns an object or if the optional assoc parameter is TRUE, an associative array is instead returned.

Report a bug 范例

Example #1 json_decode() 的例子

<?php
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';

var_dump(json_decode($json));
var_dump(json_decode($json, true));

?>
以上例程会输出:

object(stdClass)#1 (5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

array(5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

 

位运算符

 位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串,则位运算符将操作字符的 ASCII 值。

 在 32 位系统上不要右移超过 32 位。不要在结果可能超过 32 位的情况下左移。

  例子                  名称                               结果
 $a & $b     And(按位与)    将把 $a 和 $b 中都为 1 的位设为 1。
 $a | $b      Or(按位或)      将把 $a 或者 $b 中为 1 的位设为 1。
 $a ^ $b     Xor(按位异或)    将把 $a 和 $b 中不同的位设为 1。
 ~ $a      Not(按位非)    将 $a 中为 0 的位设为 1,反之亦然。
 $a << $b   Shift left(左移)    将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
 $a >> $b   Shift right(右移)    将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。

<?php教程

$a=1; 
$b=1;
echo "<br/>And(按位与)";    //将把 $a 和 $b 中都为 1 的位设为 1
echo $a&$b;      //显示值  1

echo "<br/>Or(按位或)";    //将把 $a 或者 $b 中为 1 的位设为 1
echo $a|$b;      //显示值  1

echo "<br/> Xor(按位异或)";//将把 $a 和 $b 中不同的位设为 1
echo $a^$b;      //显示值  0

echo "<br/>Not(按位非)";    //将 $a 中为 0 的位设为 1,反之亦然
echo ~$a;      //显示值  -2

echo "<br>Shift left(左移)";//将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)
echo $a<<$b;      //显示值  2

echo "<br/>Shift right(右移)";//将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。
echo $a>>$b;       //显示值 0

?>

位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串,则位运算符将操作字符的 ASCII 值。


<?php
echo 12 ^ 9; // 输出为 '5'

echo "12" ^ "9"; // 输出退格字符(ascii 8)
                    // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

echo "hallo" ^ "hello"; // 输出 ascii 值 #0 #4 #0 #0 #0
                            // 'a' ^ 'e' = #4

echo 2 ^ "3"; // 输出 1
              // 2 ^ ((int)"3") == 1

echo "2" ^ 3; // 输出 1
              // ((int)"2") ^ 3 == 1                           
?>

[!--infotagslink--]

相关文章

  • PHP session_start()很慢问题分析与解决办法

    本文章来给各位同学介绍一下关于PHP session_start()很慢问题分析与解决办法,希望碰到此问题的同学可进入参考。 最近在做东西的时候发现一个问题 有一个接口挂...2016-11-25
  • php中json_decode()和json_encode()用法与中文不显示解决办法

    本文章介绍了关于php中json_decode()和json_encode()用法与中文不显示解决办法,有需要的朋友可以参考一下下。 php中json_decode()和json_encode() 1.json_decode(...2016-11-25
  • phpexcel导出数据身份证后四位0000解决办法

    在php中我们如果要导入excel数据我们通常会使用phpexcel插件了,但是有朋友会发与使用phpexcel导出数据出现身份证后四位是0000情况了,下面我们就来看解决办法。 最...2016-11-25
  • 401错误码代表什么 401错误解决办法

    401是HTTP状态码的一种,属于“请示错误”,表示请求可能出错,已妨碍了服务器对请求的处理。具体的401错误是指:未授权,请求要求进行身份验证。登录后,服务器可能会返回对页面...2017-01-22
  • apache网站提示503错误解决办法

    Apache status 503 的原因大致有如下几种情况 : 1、 CPU 负载过高,服务器响应不过来,返回503 2、 系统连接数超限,超过MaxVhostClients的上限,返回503 3、 单IP连接数超限,超过M...2016-01-28
  • Perl CPAN::Modulelist的解决办法

    今天用CPAN安装Term::ReadLine,报了个这样的错误 Going to read /root/.cpan/sources/modules/03modlist.data.gz Can't locate object method "data" via package "C...2016-11-25
  • phpStudy访问速度慢和启动失败的解决办法

    下面给大家介绍phpstudy访问速度慢的解决办法。1、修改mysql数据库链接地址为ip地址127.0.0.1。2、使用最新版本,这个坑了我好久时间。下面一段内容是关于phpstudy启动失败的解决办法。php5.3、5.4和apache都是用vc9编...2015-11-24
  • PHP Curl出现403错误的解决办法

    自己用的小PHP应用,使用curl抓网页下来处理,为了穿墙方便,使用Privoxy作为代理,便于选择哪些网站使用proxy、哪些不用。但今天却遇到了奇怪的问题,访问google baidu这些网站居然都返回403错误,而访问其他的一些网站没事,如果...2014-05-31
  • 详解前端安全之JavaScript防http劫持与XSS

    作为前端,一直以来都知道HTTP劫持与XSS跨站脚本、CSRF跨站请求伪造。防御这些劫持最好的方法是从后端入手,前端能做的太少。而且由于源码的暴露,攻击者很容易绕过防御手段。但这不代表我们去了解这块的相关知识是没意义的,本文的许多方法,用在其他方面也是大有作用。...2021-05-24
  • PHP判断上传文件类型的解决办法

    分享给大家php判断上传文件类型的方法,大家一起学习学习。/** * 读取文件前几个字节 判断文件类型 * @return String */ function checkTitle($filename){ $file=fopen($filename, "rb"); $bin=fread($file, 2); /...2015-10-21
  • PHP分布式框架如何使用Memcache同步SESSION教程

    本教程主要讲解PHP项目如何用实现memcache分布式,配置使用memcache存储session数据,以及memcache的SESSION数据如何同步。 至于Memcache的安装配置,我们就不讲了,以前...2016-11-25
  • android.os.BinderProxy cannot be cast to com解决办法

    本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20
  • MYSQL数据库使用UTF-8中文编码乱码的解决办法

    1.用phpmyadmin创建数据库和数据表 创建数据库的时候,请将“整理”设置为:“utf8_general_ci” 或执行语句: 复制代码 代码如下:CREATE DATABASE `dbname` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; 创...2015-10-21
  • php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法

    最近遇到一个问题,就是在使用php的mail函数发送utf-8编码的中文邮件时标题出现乱码现象,而邮件正文却是正确的。最初以为是页面编码的问题,发现页面编码utf-8没有问题啊,找了半天原因,最后找到了问题所在。 1.使用 PEAR 的...2015-10-21
  • PHP页面转UTF-8中文编码乱码的解决办法

    对于乱码这个问题php开发者几乎都会有碰到过,我们下面主要是介绍了php文件乱码和页面乱码。PHP页面转UTF-8编码问题 1.在代码开始出加入一行: header("Content-Type: text/html;charset=utf-8"); 2.PHP文件编码问题...2015-10-21
  • 详解C#中的session用法

    这篇文章主要介绍了C#中的session用法 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • 安全地关闭MySQL服务的教程

    普通关闭 我的mysql是自己下载的tar包,自己设定安装目录来安装的。停止mysql服务,说来简单,但不知道的话,还真是挠头。在这和mysql入门的同学们共享:)正确方法是,进入mysql的bin目录下,然后执行./mysqladmin -uroot -p shut...2015-11-24
  • Python3使用Selenium获取session和token方法详解

    这篇文章主要介绍了Python3使用Selenium获取session和token方法详解,需要的朋友可以参考下...2021-02-17
  • Android开发之PhoneGap打包及错误解决办法

    下面来给各位简单的介绍一下关于Android开发之PhoneGap打包及错误解决办法,希望碰到此类问题的同学可进入参考一下哦。 在我安装、配置好PhoneGap项目的所有依赖...2016-09-20
  • Ubuntu15下mysql5.6.25不支持中文的解决办法

    apt-get install 安装的,不是源码包安装的mysql1 修改mysql的配置文件/etc/mysql/conf.d/mysql.cnf在[mysql]的下方加入如下语句:(注:这个文件下没有配置,只有【mysql】)no-auto-rehash default-character-set=utf8/etc/...2015-10-21