PHP session和cookie
<?php //===========================================================cookie //cookie是在服务器端被创建并写回到客户端浏览器,浏览器接到响应头中关于写cookie的指令则在本地临时文件夹中创建了一个cookie文件,其中保存了cookie内容,cookie内容的存储是键值对的方式,键和值都只能是字符串 //cookie标题头必须在发送其他标题头之前发送,否则就无效(这是cookie的限制,而不是PHP的限制)。 //服务器在发送 cookie 时,cookie 的值会自动进行 URL 编码,在取回时进行自动解码。如不想 URL 编码,请使用 setrawcookie() 取代 setcookie(),setrawcookie() 与 setcookie() 几乎完全相同,不同的是不会在发往客户机时,对 cookie 值进行自动 URL 编码。 //cooke有四个标识符(用来判断是否同一个cookie):cookie的name,domain,path,secure标记。要想在将来改变这个cookie的值,需要发送另一个具有相同cookie name,domain,path的Set-Cookie消息头,这将以一个新的值来覆盖原来cookie的值。然而,如果仅仅只是改变这些选项的某一个也会创建一个完全不同的cookie,如只是更改了domain值,(secure应为网站整体统一配置,一般不单独修改) //当一个cookie被设置好或已存在,并且可选条件允许的话,该cookie的值会在接下来的每个请求中被发送至服务器。cookie的值被存储在名为Cookie的HTTP消息头中,并且只包含了cookie的值,其它的选项全部被去除。例如:Cookie : value //Set-Cookie指定的属性选项只是应用于浏览器端,一旦属性选项被设置后便不会被服务器重新取回。浏览器中传递的cookie值与Set-Cookie中指定的值是完全一样的字符串;对于这些值不会有更近一步的解析或转码操作。如果在指定的请求中有多个cookies,那么它们会被分号和空格分开,例如:Cookie:value1 ; value2 ; name1=value1 //通常设置cookie格式如下,各参数顺序随意,紧跟cookie值后面的每个选项都以分号和空格分割,并且每个选项都指定cookie什么条件下应该被发送到服务器。 //name即为此cookie的键值名称。value为对应值 //expires,值是当前时间戳+有效时长秒数,其指定了cookie何时不会再被发送到服务器端的,因此过期后cookie可能会被浏览器删掉。在没有expires选项时,cookie的寿命仅限于单一的会话中。浏览器的关闭意味这一次会话的结束,所以会话cookie只存在于浏览器保持打开的状态之下。这就是为什么当登录到一个web应用时经常看到一个checkbox,询问是否选择存储登录信息:如果选择是的话,那么一个expires选项会被附加到登录的cookie中。如果expires选项设置了一个过去的时间点,那么这个cookie会被立即删除 //path,与domain选项相同的是,path指明了浏览器在发cookie消息之前必须在请求url中存在一个指定url路径。这个比较是通过将path属性值与请求的URL从头开始逐字符串比较完成的。如果字符匹配,则发送cookie消息头,例如:"path=/blog"。通常该值设置为"path=/",即所有路径包含 "/" 的请求浏览器都会发送该cookie(前提同时满足domain值) //domain,指示浏览器把本地的cookie将要发送到哪些以domain值结尾的域名中,注意domain值的第一个字符必须是".",列如 "domain=.google.com" 则所有以"google.com"结尾的域名都可以访问该cookie。默认情况下,domain会被设置为创建该cookie的页面所在的域名。想象诸如Yahoo!这样的大型网站都会有许多以name.yahoo.com(例如:my.yahoo.com,finance.yahoo.com,等等)为格式的站点。单独的一个cookie可以简单的通过将其domain选项设置为yahoo.com而发送到所有这些站点中。浏览器会对domain的值与请求所要发送至的域名,做一个尾部比较(即从字符串的尾部开始比较),并且在匹配后发送cookie消息 //secure,不像其它选项,该选项只是一个标记并且没有其它的值。一个secure cookie只有当请求是通过SSL和HTTPS创建时,才会发送到服务器端。 //httpOnly,禁止浏览器端js通过document.cookie属性访问cookie,以下有详解 header("Set-Cookie:name=value [ ;expires=date][ ;path=path][ ;domain=domain][ ;secure][ ;httpOnly]"); //cookie会被浏览器自动删除,通常存在以下几种原因: /* 会话cooke(Session cookie)在会话结束时(浏览器关闭)会被删除 持久化cookie(Persistent cookie)在到达失效日期时会被删除 如果浏览器中的cookie限制到达,那么cookies会被删除以为新建cookies创建空间。 */ //Cookie限制条件 /* 在cookies上存在了诸多限制条件,来阻止cookie滥用并保护浏览器和服务器免受一些负面影响。有两种cookies的限制条件:cookies的属性和cookies的总大小。原始的规范中限定每个域名下不超过20个cookies,早期的浏览器都遵循该规范,并且在IE7中有个更近一步的提升。在微软的一次更新中,他们在IE7中增加cookies的限制到50个,与此同时Opera限定cookies个数为30.Safari和Chrome对与每个域名下的cookies个数没有限制。 发向服务器的所有cookies的最大数量(空间)仍旧维持原始规范中所指出的:4KB。所有超出该限制的cookies都会被截掉并且不会发送至服务器。 */ //HttpOnly cookies /* 微软的IE6 SP1在cookies中引入了一个新的选项:HTTP-only cookies.HTTP-Only背后的意思是告之浏览器该cookie绝不应该通过Javascript的document.cookie属性访问。设计该特征意在提供一个安全措施来帮助阻止通过Javascript发起的跨站脚本攻击(XSS)窃取cookie的行为(我会在另一篇博客中讨论安全问题,本篇如此已足够)。今天Firefox2.0.0.5+,Opera9.5+,Chrome都支持HTTP-Only cookies。3.2版本的Safari仍不支持。 要创建一个HTTP-Only cookie,只要向cookie中添加一个HttpOnly标记即可,例如: header("Set-Cookie:name=value; HttpOnly"); 也可以在php.ini中设置 session.cookie_httponly = 1 或者在PHP代码中输入 ini_set("session.cookie_httponly", 1); 不能通过JavaScript设置HTTP-only cookies,因为不能再通过JavaScript读取这些cookies,这是情理之中的事情。 */ $cookieValue = 'cookieValue'; //以下两种方法均可以创建cookie //1, header("Set-Cookie:cookieName=$cookieValue;expire=".(time()+3600).";path=/;domain=.google.com;secure;httpOnly"); //2, setcookie("cookieName", $cookieValue, time()+3600,"/",".google.com",true,true); echo $_COOKIE["cookieName"]; //清除cookie setcookie("cookieName", '', time()+3600,"/",".google.com",true,true); //或 setcookie("cookieName", $cookieValue, time()-1,"/",".google.com",true,true); //$HTTP_COOKIE_VARS["cookieName"] 与 $_COOKIE["cookieName"] 均可获取 cookieName 的 cookie 的值。 //以下为安全设置,设置 cookie 保存的 session_id 只在 https 中传递,最好在 session_start(); 之后执行 setcookie(session_name(), session_id(), 0, "/",'.google.com',true); session_set_cookie_params(0,'/','.google.com',true,true); //===========================================================session /* 浏览器访问页面 a.php 时候,服务器产生一个 session 文件,将其存放在服务器,同时将 session_id 发送给浏览器,浏览器将其保存到 cookie ,浏览器在访问 b.php 时候,从 cookie 中获取 session_id 发送到服务器,服务器根据 session_id 获取相应 session 内容 如果浏览器禁用cookie,怎么使用session呢?这时需要使用url重写的方式 url重写分为自动和手动。 自动模式: 自动重写url就是配置 php.ini ,开启透明的SID,其他程序不变,自动重写 url 不安全,不建议使用。 开启透明SID,需要修改的php.ini是: session.use_trans_sid = 1 //由默认 0 改为 1 session.use_only_cookies = 0 //由默认 1 改为 0 session.use_cookies = 0 //由默认 1 改为 0,该参数的值不影响上述机制的进行。这个可改可不改 手动模式: index.php 页代码 //=========================== index.php 页开始=========================== session_start (); $_SESSION ['name'] = "testname"; $_SESSION ['age'] = 100; echo 'session save succes! click <a href="index2.php?' . SID . '">here</a> to see SID<br/>'; //=========================== index.php 页结束=========================== index2.php 页代码 //=========================== index2.php 页开始=========================== if ($_GET ["PHPSESSID"]) { //将从url获取的session_id,赋给程序,让程序使用指定session_id的会话 session_id ( $_GET ["PHPSESSID"] ); } session_start (); echo session_id () . '<br/>'; echo $_SESSION ['name']; //=========================== index2.php 页结束=========================== 在浏览器上输入地址 http://localhost/test/index.php 点击页面链接后会跳转到地址 http://localhost/test/index2.php? 并且显示内容 m1n82u8sk2lkqb5rpi5purrfn5 testname 这里 m1n82u8sk2lkqb5rpi5purrfn5 即为本次会话的 session_id 自动模式,会将url后面自动添加PHPSESSID参数,所以在index.php中去掉SID即可,index2.php不变 */ //凡是需要使用 session 的php文件起始输出内容前都要执行此方法。除非用框架全局只需要执行一个index.php文件,那么在index.php文件中写一次该方法即可 session_start(); //输出当前session会话id,每个会话id唯一 echo session_id () . '<br/>'; //输出php.ini设置的session名,这里是 PHPSESSID,也是 cookie 里的键值,对应值就是session_id echo session_name(). '<br/>'; //输出cookie里存的 session_id,浏览器的cookie只保存session的id不保存session里的值 echo $_COOKIE[session_name()] . '<br/>'; //设置session $_SESSION['sessionName'] = "sessionValue"; //使用session echo $_SESSION['sessionName']; //销毁session //退出登录前执行 setcookie(session_name(), session_id(), time() -1); //这会删除所有的$_SESSION数据,刷新后,有COOKIE传过来,但是没有数据。 $_SESSION = array(); //这个作用更彻底,删除$_SESSION 删除session文件,和session_id session_destroy(); /* session.gc_maxlifetime = 1440 //session数据默认存在时间是1440s(24分钟),当session文件在1440s后没被访问的话,则该session被视为“垃圾文件”,并且等待 gc(垃圾回收) 进程的调用时候被清理掉 ;session.save_path = "/tmp" //默认未启用,改变sesion文件存放路径,一般为了保证服务器的安全,session.save_path 值最好设置为外网无法访问的目录,另外如果是在 linux 服务器下进行 session 配置,请务必同时配置此目录为可读写权限,否则在执行 session 操作时会报错 session.auto_start = 0 //session使用前,要先进行初始化 session_start(); 如果嫌麻烦,可以将 session.auto_start 值设为1自动初始化,(此设置不推荐,最好默认0) session.cookie_lifetime = 0 //默认为0,传递 session_id 的 cookie 有效期(秒),0表示仅在浏览器打开期间有效。以秒数指定了发送到浏览器的cookie的生命周期,值为0表示“直到关闭浏览器”。 session.name = PHPSESSID //这里设置的 PHPSESSID 作为 cookie 的键值来获取 对应的 session_id 值。如 echo $_COOKIE["PHPSESSID"]; 就会输出 session_id 值 m1n82u8sk2lkqb5rpi5purrfn5(本次会话 session_id 值) session.gc_probability = 1 //查看如下 session.gc_divisor session.gc_divisor = 100 //定义在每次初始化会话时,启动垃圾回收进程的概率。计算公式如下:session.gc_probability/session.gc_divisor,这里是 1/100,表示有 1% 的概率启动启动垃圾回收程序,对会话页面访问越频繁,概率就应当越小。建议值为 1/1000~5000。 session.use_trans_sid = 0 //开启后,默认为每个url后添加了session_name=session_id session.use_only_cookies = 1 //是否只使用cookie来保存传递 session_id值。当 session.use_trans_sid 为1有效时,session.use_only_cookies 一定要设置为 0 无效。如果该参数为1时,则即使 session.use_trans_sid = 1 也无效,此时禁止用户通过 url 来传递 session_id,客户端如果禁用 cookie 将使 session 无法工作。 session.use_cookies = 1 //设置客户端是否使用cookie来保存session值 */ //如果是多服务器共用session则最好将session以session_id为键值保存到数据库或独立共享的服务器中