PHP 之session cookie-阿里云开发者社区

开发者社区> 安全> 正文

PHP 之session cookie

简介:

cookie和session有什么用?
   常见的用法,比如在有些网站下载东西需要会员先登陆。http协议本身是无状态的,无法得知顾客是否已经登陆,怎么办呢?cookie和session就可以知道。再比如网上购物,用户身份认证,程序状态记录。购物车怎么知道顾客挑选过哪些商品呢?cookie和session也可以记录。总而言之,cookie和session就是能够记录顾客状态的技术,尽管二者属于不同的技术,但只要cookie能做到的,session也能做到!如果session和cookie一样安全的话,二者就没有并要同时存在了,只要cookie就好了,让客户端来分提服务器的负担,并且对于用户来说又是透明的。何乐而不为呢。

1.  什么是session?
         Session的中文译名叫做“会话”,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。
     因此通过SESSION(cookie是另外一种解决办法)记录用户的有关信息,以供用户再次以此身份对web服务器提起请求时作确认。会话的发明使得一个用户在多个页面间切换时能够保存他的信息。网站编程人员都有这样的体会,每一页中的变量是不能在第三页中使用的(虽然form,url也可以实现,但这都是非常不理想的办法),而SESSION中注册的变量就可以作为全局变量使用了。SESSION的实现中采用COOKIE技术,SESSION会在客户端保存一个包含session_id(SESSION编号)的COOKIE;在服务器端保存其他session变量,比如session_name等等。当用户请求服务器时也把session_id一起发送到服务器,通过session_id提取所保存在服务器端的变量,就能识别用户是谁了。同时也不难理解为什么SESSION有时会失效了。当客户端禁用COOKIE时(点击IE中的“工具”—“Internet选项”,在弹出的对话框里点击“安全”—“自定义级别”项,将“允许每个对话COOKIE”设为禁用),session_id将无法传递,此时SESSION失效。不过PHP5在linux/unix平台可以自动检查cookie状态,如果客户端设置了禁用,则系统自动把session_id附加到url上传递。windows主机则无此功能。

 

a域名的网站,我登陆成功.怎样到b域名的网站,也能获得session?

在 www.a.com 上登陆后,去 www.b.com 的连接中带有 形如 http://www.b.com/xxxx.php?s=yyyyyyyyyy 的
其中 yyyyyyyyyy 是在 www.a.com 中 session_id(); 的值,如果a,b在同一个服务器,直接读取文件。不在的话,b可以调用a的接口(a需要接口实现)

根据session文件获取session信息

Java代码  收藏代码
  1. $sessionPath = session_save_path();  
  2. $sessionFile = $sessionPath . DS . 'sess_' . $sid;//sid是sessionid  
  3. if (file_exists($sessionFile) && (time() - filectime($sessionFile)) < $liftTime) {  
  4.     $lock = new CacheLock($sid);  
  5.     $lock->lock();  
  6.     $content = file_get_contents($sessionFile);  
  7.     $tempSession = $_SESSION;  
  8.     $_SESSION = array();  
  9.     session_decode($content); //成功回写$_SESSION  
  10.     $result['info']['customer_id'] = $_SESSION['customer_gm']['id'];  
  11.     $result['info']['customer_name'] = $_SESSION['customer_gm']['name'];  
  12.     $result['info']['customer_email'] = $_SESSION['customer_gm']['email'];  
  13.     $result['msg'] = '';  
  14.     $result['success'] = 1;  
  15.     $_SESSION = $tempSession;  
  16.     $lock->unlock();  
  17. }  

2.  Session常见函数及用法?
● 注册SESSION变量:
PHP5使用$_SESSION[‘xxx’]=xxx注册SESSION全局变量。和GET,POST,COOKIE的使用方法相似。

Page1.php

Java代码  收藏代码
  1. <?php  
  2. session_start(); //使用SESSION前必须调用该函数。  
  3. $_SESSION['passwd'] = 'mynameislikui';  
  4. $_SESSION['time'] = time();  
  5. echo '<br/><a href="page2.php">通过COOKIE传递SESSION</a>'//如果客户端支持cookie,可通过该链接传递session到下一页。  
Page2.php
Java代码  收藏代码
  1. <?php  
  2. session_start();  
  3. echo $_SESSION['name']; //  
  4. echo $_SESSION['passwd']; //  
  5. echo date('Y m d H:i:s', $_SESSION['time']);  
  6. echo '<br /><a href="page1.php">返回山一页</a>';  
  7. ?>  
有两种方法传递一个会话 ID:
cookie  cookie 更优化,但由于不总是可用
URL 参数 直接将会话 ID 嵌入到 URL 中间去。 
   ● session_id
       session_id() 用于设定或取得当前session_id。php5中既可以使用session_id(),也可以通过附加在url上的SID取得当前会话的session_id和session_name。如果session_id()有具体指定值的话,将取代当前的session_id值。使用该函数前必须启动会话:session_start();当我们使用session cookies时,如果指定了一个session_id()值,每次启动session_start()都会往客户端发送一个cookie值。不论当前session_id是否与指定值相等。session_id()如果没有指定值,则返回当前session_id();当前会话没有启动的话,则返回空字符串。
● 更改 session_id session_regenerate_id() 更改成功则返回true,失败则返回false。使用该函数可以为当前session更改session_id,但不改变当前session的其他信息。例如:
Java代码  收藏代码
  1. <?php  
  2. session_start();  
  3. $old_sessionid = session_id();  
  4. session_regenerate_id();  
  5. $new_sessionid = session_id();  
  6. echo "原始 SessionID: $old_sessionid<br/>";  
  7. echo "新的 SessionID: $new_sessionid<br/>";  
  8. echo"<pre>";  
  9. print_r($_SESSION);  
  10. echo"</pre>";  
  11. ?>  
● session_name() 返回当前session的name或改变当前session的name。如果要改变当前session的name,必须在session_start()之前调用该函数。注意:session_name不能只由数字组成,它至少包含一个字母。否则会在每时每刻都生成一个新的session id.
session改名示例:
Java代码  收藏代码
  1. <?php  
  2. $previous_name = session_name("WebsiteID");  
  3. echo "新的session名为: $previous_name<br/>";  
  4. ?>  
 ● 如何删除session?
下面是PHP官方关于删除session的案例:
Java代码  收藏代码
  1. <?php  
  2. // 初始化session.  
  3. session_start();  
  4. /*** 删除所有的session变量..也可用unset($_SESSION[xxx])逐个删除。****/  
  5. $_SESSION = array();  
  6. /***删除sessin id.由于session默认是基于cookie的,所以使用setcookie删除包含session id的cookie.***/  
  7. if (isset($_COOKIE[session_name()])) {  
  8.     setcookie(session_name(), '', time() - 42000'/');  
  9. }  
  10. // 最后彻底销毁session.  
  11. session_destroy();  
  12. ?>  
由此我们可以得出删除Session的步骤:
①session_start()
②$_SESSION=array()/unset($_SESSION['xxx'])
③session_destroy()
● SESSION安全:
       会话模块不能保证存放在会话中的信息只能被创建该会话的用户看到。根据其存放的数据,还需要采取更多措施来主动保护会话的完整性。 
       评估会话中携带的数据并实施附加保护措施通常要付出代价,降低用户的方便程度。例如,如果要保护用户免于受简单的社交策略侵害(注:指在 URL 中显示的会话 ID 会被别人在电脑屏幕上看到,或被别的网站通过 HTTP Referer 得到等),则应该启用 session.use_only_cookies。此情形下,客户端必须无条件启用 cookie,否则会话就不工作。 
       有几种途径会将现有的会话 ID 泄露给第三方。泄露出的会话 ID 使第三方能够访问所有与指定 ID 相关联的资源。第一,URL 携带会话 ID。如果连接到外部站点,包含有会话 ID 的 URL 可能会被存在外部站点的 Referer 日志中。第二,较主动的攻击者可能会侦听网段的数据包。如果未加密,会话 ID 会以明文方式在网络中流过。对此的解决方式是在服务器上实施 SSL 并强制用户使用。
      默认情况下,所有与特定会话相关的数据都被存储在由 INI 选项 session.save_path 指定的目录下的一个文件中(session文件的命名格式是:"sess_[PHPSESSID的值]"。每一个文件,里面保存了一个会话的session_encode数据)。对每个会话会建立一个文件(不论是否有数据与该会话相关)。这是由于每打开一个会话即建立一个文件,不论是否有数据写入到该文件中。注意由于和文件系统协同工作的限制,此行为有个副作用,有可能造成用户定制的会话处理器(例如用数据库)丢失了未存储数据的会话。
上面介绍函数下文将会用到,但还有一些有关session的函数也介绍一下:
session_encode
函数功能:sesssion信息编码
函数原型:string session_encode(void);
返回值:字符串
功能说明:返回的字符串中包含全局变量中各变量的名称与值,形式如:a|s:12:"it is a test \";c|s:4:"lala"; a是变量名 s:12代表变量a的值"it is a test的长度是12 变量间用分号”;”分隔。
session_decode
函数功能:sesssion信息解码
函数原型:boolean session_decode (string data)
返回值:布尔值
功能说明:这个函数可将session信息解码,成功则返回逻辑值true
PHP5不再使用session_id,而是把它变成一个常量SID,并保存在cookie中。如果客户端禁用了cookie,php会自动通过url自动传动传递SID,其条件是设置php.ini中的session.use_trans_sid = 1。此时即使客户端即使禁用了cookie也没关系了。
用 strip_tags() 来输出 SID 以避免 XSS 相关的攻击。

Session跨页传递问题:
session跨页传递需要考虑三种情况:
①客户端禁用了cookie。
②浏览器出现问题,暂时无法存取cookie
③php.ini中的session.use_trans_sid = 0或者编译时没有打开--enable-trans-sid选项
为什么会这样呢?下面解释一下原因:
Session文件分为两部分:session变量保存在服务器端(默认以文件方式存储session);而session id则以cookie形式保存在客户端。(注意:session默认是基于cookie的)。
当用户的浏览器向服务器提出请求时,同时发送包含session id的cookie(默认情况下)。服务器根据客户端提供的session id来得到用户的文件,即保存在服务器端的session变量值。事实上,session id可以使用客户端的Cookie或者Http1.1协议的Query_String(就是访问的URL的“?”后面的部分)来传送给服务器,然后服务器读取Session的目录。PHP中的session在默认情况下是使用客户端的Cookie来保存session id的,所以当客户端的cookie出现问题的时候就会影响session了。必须注意的是:session不一定必须依赖cookie,这也是session相比cookie的高明之处。
当客户端的Cookie被禁用或出现问题时,PHP会自动把session id附着在URL中,这样再通过session id就能跨页使用session变量了。但这种附着也是有一定条件的:
其一:“php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项”;
其二:运行PHP的服务器必须是unix/linux系统,windows不具备此项功能。
明白了以上的道理,我们就可以得出解决session跨页传递问题的三条途径:
1、设置php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项,让PHP自动跨页传递session id。
2、手动通过URL传值、隐藏表单传递session id。
3、用文件、数据库等形式保存session_id,在跨页过程中手动调用。
Java代码  收藏代码
  1. <?php  
  2. session_start();  
  3. $_SESSION['var1']="中华人民共和国";  
  4. $sn = session_id();  
  5. $url='<a href="s2.php?s='.$sn.'">下一页</a>';//客户端不支持cookie时,使用该办法传递session.      
  6. echo $url;  
  7. ?>  
 s2.php
Java代码  收藏代码
  1. <?php  
  2. session_id($_GET['s']);  
  3. session_start();  
  4. echo "传递的session变量var1的值为:".$_SESSION['var1'];  
  5. ?>  
 二,什么cookie
cookie分为二种
1,以文件方式存在硬盘空间上的长期性的cookie
2,停留在浏览器所占内存中的临时性的cookie
浏览网站时,你会经常发现网站登录的地方,会有提示,问你是不是要记住自己的登录状态,像这种情况,登录时填写的一些信息会被以文件的方式存放在客户端的硬盘上。
当用户登录后,session会在cookie端产生一个session_id,这个session_id是存于浏览器所占用的内存当中。当你关闭浏览器后,session_id也要消失了。
cookie采用的是在客户端保持状态的方案,它是客户端的会话状态的一种储存机制。它 是服务器在本地机器上存储的小段文本或者是内存中的一段数据,并随每一个请求发送至同一个服务器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie规范。网络服务器用HTTP头信息向客户端发送cookies,在客户终端,浏览器解析这些cookies并将它们保存为一个本地文 件,或者本地内存中数据,它会自动将同一服务器的任何请求缚上这些cookies,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以 session机制借助于cookie机制来达到保存标识的目的,这样就可以解决HTTP协议无状态的缺陷。
Java代码  收藏代码
  1. <?php  
  2. if ($_GET[out])  
  3. //注销cookie方法  
  4.     setcookie('name''');  
  5.     setcookie('pwd''');  
  6.     echo "<script>location.href='cookie.php'</script>";  
  7. }  
  8.   
  9. if ($_POST[uname] && $_POST[upwd]) { //cookie的配置  
  10.     setcookie('name', $_POST[uname], time() + 3600);  
  11.     setcookie('pwd', $_POST[upwd], time() + 3600);  
  12. //让它跳转一次进行刷新  
  13.     echo "<script>location.href='cookie.php'</script>";  
  14. }  
  15.   
  16. if ($_COOKIE[name] && $_COOKIE[pwd]) { //cookie的应用  
  17.     echo '用户:' . $_COOKIE[name] . '<br>密码:' . $_COOKIE[pwd];  
  18. //写个超级链接注销cookie  
  19.     echo "<br><br><a href='cookie.php?out=out'>注销cookie</a>";  
  20. // else echo "cookie保存失败!";  
  21. else echo "请登录!!!";  
  22. ?>  
  23.   
  24. <form action='' method="post">  
  25.     用户:<input type="text" name='uname' value=''><br><br>  
  26.     密码:<input type="text" name='upwd'><br><br>  
  27.     <input type="submit" name='sub' value='登录'>  
  28. </form>  

二级域名共享cookies

我们通常在使用cookie的时候一般都只是局限在本站内使用,也就是只在一个域名下使用。

如我们要在www.xhbin.com下使用一个cookie的话 ,只要在这个站下面的文件中设置一个cookie就行了

但是如果我们要想实现在一级域名下设置的cookie,同时要在二级域名下使用的话那么该怎么做呢??

比如这样的情况:我们在一级域名是个网站如:www.xhbin.com,他的下面有个二级域名如:bbs.xhbin.com

我们要想实现在一级域名上登录后,保留这个cookie到二级域名上,也就是说,实现同步登录的效果,

那么我们该怎么设置这个cookie??其实很简单。

就拿刚刚那个域名(www.xhbin.com)来说,我们可以这样设置cookie:setcookie(“fangbinbin”,”mengfei”,time()+3600,”/”,”.xhbin.com”);

那么我们就可以在这www.xhbin.com  和bbs.xhbin.com下面直接使用(echo $_COOKIE['fangbinbin']; )就能够输出那个设置的cookie的值了

这样子就解决了那个同步登录的问题!!当然如果涉及到3个及其以上的域名,最好都有统一的登录界面和退出界面,如登录时统一POST到一级域名的登录页面。
再将这个Cookie的所涉及到的用户登录Session信息保存到Key-Value类型的缓存中,如memcached、 memcachedDB 等,尽量避免写文件或者DB降低IO,提供用户体验。
session存cookie
session 的生命周期是有一次,但是不同的页面要用同一个session变量的话,就需要在不同的页面加上session_start(),不然你是在另一个页面用 不了session的,所以为了方便就用session_set_cookie_params把session变量存在cookie中就可以正常使用 session了 ,这样就不用在每个页面都要调用session_start()

Java代码  收藏代码
  1. session_save_path($path);  
  2. session_set_cookie_params(0'/''.trip166.com');  
  3. session_start();  
然后在firefox下web Developer 中的查看cookie看你的session 的id的作用域,如果为.trip166.com,则说明cookie有效,session_id 全域有效,不出意外,你能取得session。
cookie安全 cookiekey和浏览器挂钩
Php代码  收藏代码
  1. $auth_key = md5($salt.$_SERVER['HTTP_USER_AGENT']);    
然后加密解密$auth_key,判断当前的和cookie中的$auth_key
PHP - 利用P3P实现跨域
Java代码  收藏代码
  1. <?php    
  2. header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');    
  3. setcookie("test"'124', time()+3600"/"".a.com");    
  4. ?>    

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
+ 订阅

云安全开发者的大本营

其他文章