session & cookie

cookie:

注意一:如果不设置过期时间,则表示这个cookie的生命期 为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不 存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些 cookie仍然有效直到超过设定的过期时间。


    存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式。对于 IE,在一个打开的窗口上按Ctrl-N(或者从文件菜单)打开的窗口可以与原窗口共享,而使用其他方式新开的IE进程则不能共享已经打开的窗口的内存 cookie;对于Mozilla Firefox0.8,所有的进程和标签页都可以共享同样的cookie。一般来说是用javascript的window.open打开的窗口会与原窗 口共享内存cookie。浏览器对于会话cookie的这种只认cookie不认人的处理方式经常给采用session机制的web应用程序开发者造成很 大的困扰。

session:

注意一

session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。 

    当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。 

    保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID,

在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家 提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程 序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所 以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的 HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。 

    恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。

关于php中session的配置:

一:关于session.save_path是多级目录的问题:

; The path can be defined as:
;
;     session.save_path = "N;/path"
;
; where N is an integer.  Instead of storing all the session files in
; /path, what this will do is use subdirectories N-levels deep, and
; store the session data in those directories.  This is useful if you
; or your OS have problems with lots of files in one directory, and is
; a more efficient layout for servers that handle lots of sessions.
;
; NOTE 1: PHP will not create this directory structure automatically.
;         You can use the script in the ext/session dir for that purpose.
; NOTE 2: See the section on garbage collection below if you choose to
;         use subdirectories for session storage

当使用多层目录存储session文件时:

好处:更有有效的处理session文件

坏处:对session的垃圾回收机制产生影响,使自动回收垃圾不管用了,需要自己写shell来处理这些过期的文件。

; NOTE: If you are using the subdirectory option for storing session files
;       (see session.save_path above), then garbage collection does *not*
;       happen automatically.  You will need to do your own garbage
;       collection through a shell script, cron entry, or some other method.
;       For example, the following script would is the equivalent of
;       setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes):
;          find /path/to/sessions -cmin +24 -type f | xargs rm

注意二:sesion id 的生成算法,session.hash_function = 0 

; Select a hash function for use in generating session ids.
; Possible Values
;   0  (MD5 128 bits)
;   1  (SHA-1 160 bits)
; This option may also be set to the name of any hash function supported by
; the hash extension. A list of available hashes is returned by the hash_algos()
; function.
; http://php.net/session.hash-function
session.hash_function = 0

虽然用的md5但是测试结果发现sess_t9175fqbkjklfhcre3fndqn6f7  实际上仅仅生成了26位的值(猜测可能是session_start()按md5生成session id 后截取的值)

注意四:服务端存储session数据的方式,session.serialize_handler = php

; Handler used to serialize data.  php is the standard serializer of PHP.
; http://php.net/session.serialize-handler
session.serialize_handler = php

测试结果:虽然是按php的序列话方式来存储的,但是手动测试反序列化的时候出错:

        $var = 'name|s:9:"王乐乐";book|s:7:"english"';
        $a = unserialize($var, true);
        var_dump($a);     //返回false
        exit;

注意五:由于无法将一个引用恢复到另外一个变量, 所以不可以将引用保存到会话变量中。

注意六:

无论是通过调用函数 session_start() 手动开启会话, 还是使用配置项 session.auto_start 自动开启会话, 对于基于文件的会话数据保存(PHP 的默认行为)而言, 在会话开始的时候都会给会话数据文件加锁, 直到 PHP 脚本执行完毕或者显式调用 session_write_close() 来保存会话数据。 在此期间,其他脚本不可以访问同一个会话数据文件。

对于大量使用 Ajax 或者并发请求的网站而言,这可能是一个严重的问题。 解决这个问题最简单的做法是如果修改了会话中的变量, 那么应该尽快调用 session_write_close() 来保存会话数据并释放文件锁。 还有一种选择就是使用支持并发操作的会话保存管理器来替代文件会话保存管理器。

 

注意七:会话什么时候保存数据呢?

当 PHP 关闭的时候(或者调用了 session_write_close() 之后), PHP 会对 $_SESSION 中的数据进行编码, 然后和会话 ID 一起传送给 write 回调函数。 write 回调函数调用完毕之后,PHP 内部将调用 close 回调函数。

session_write_close()   http://php.net/manual/zh/function.session-write-close.php

 

注意八:什么是会话管理器? (http://php.net/manual/zh/session.customhandler.php)

 

注意九:检验session是否开启了

<?php
/**
* @return bool
*/
function is_session_started()
{
    if ( php_sapi_name() !== 'cli' ) {
        if ( version_compare(phpversion(), '5.4.0', '>=') ) {
            return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
        } else {
            return session_id() === '' ? FALSE : TRUE;
        }
    }
    return FALSE;
}

// Example
if ( is_session_started() === FALSE ) session_start();
?>

 参考:http://php.net/manual/zh/function.session-status.php#111945

注意十:常见session攻击方法:

 

Cookies是作为http的一个扩展诞生的,其主要用途是弥补http的无状态特性,提供了一种保持客户端与服务器端之间状态的途径

原文地址:https://www.cnblogs.com/Alight/p/4087244.html