<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[写得好，转载：浅谈PHP中的Session机制]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Sat, 05 Jun 2010 07:03:01 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	<textarea name="code" class="php" rows="15" cols="100">
&lt;?php
session_destroy();
?&gt;
</textarea><br/><br/><br/>做web开发，必然会涉及到Session，这是由于http协议本身是无状态的（每次响应都是独立的，彼此间没有联系），所以如果需要在页面跳转间保持某个用户的身份，就要在每次连接时告诉服务器端你的唯一标示号，即Session ID。这样，服务器端便可通过Session ID得到所需的数据。<br/><br/>在PHP中，Session是通过$_SESSION这个全局变量来set/get的，不过在使用之前要先初始化。初始化是通过session_start函数（如果php.ini中将session.auto_start设为1，则会自动初始化），之后PHP会为request自动生成一个唯一随机数作为Session ID，生成算法默认提供了MD5 (128 bits) 和SHA-1 (160 bits)，由php.ini中session.hash_function设定。其实也可以自定义，比如在随机数基础上将来访者的IP地址也加入到算法中，像CodeIgniter1.7.2中代码：<br/><br/><div class="code">$sessid = &#039;&#039;;<br/>while (strlen($sessid) &lt; 32)<br/>&#123;<br/>&nbsp;&nbsp;$sessid .= mt_rand(0, mt_getrandmax());<br/>&#125;<br/>// To make the session ID even more secure we&#039;ll combine it with the user&#039;s IP<br/>$sessid .= $this-&gt;CI-&gt;input-&gt;ip_address();<br/>$sessid = md5(uniqid($sessid, TRUE))</div><br/><br/>生成的ID存放在服务器的某一目录下，这由php.ini中session.save_path配置。如果要在多个服务器中同步session id，你可以将其存放在数据库或共享缓存中。这需要你自定义一系列Session的读写方法，并在调用session_start函数前先设定好，以下面代码为例(来自php document中的一段示例代码)：<br/><br/><div class="code">CREATE TABLE `ws_sessions` ( <br/>&nbsp;&nbsp;`session_id` varchar(255) BINARY NOT NULL DEFAULT &#039;&#039;, <br/>&nbsp;&nbsp;`session_expires` int(10) UNSIGNED NOT NULL DEFAULT &#039;0&#039;, <br/>&nbsp;&nbsp;`session_data` text, <br/>&nbsp;&nbsp;PRIMARY KEY&nbsp;&nbsp;(`session_id`) <br/>) TYPE=InnoDB;</div><br/><br/><br/><br/><div class="code">&lt;?php <br/>class session &#123; <br/>&nbsp;&nbsp; // session-lifetime <br/>&nbsp;&nbsp; var $lifeTime; <br/>&nbsp;&nbsp; // mysql-handle <br/>&nbsp;&nbsp; var $dbHandle; <br/>&nbsp;&nbsp; function open($savePath, $sessName) &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // get session-lifetime <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;lifeTime = get_cfg_var(&quot;session.gc_maxlifetime&quot;); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // open database-connection <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $dbHandle = @mysql_connect(&quot;server&quot;,&quot;user&quot;,&quot;password&quot;); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $dbSel = @mysql_select_db(&quot;database&quot;,$dbHandle); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // return success <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!$dbHandle &#124;&#124; !$dbSel) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;dbHandle = $dbHandle; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true; <br/>&nbsp;&nbsp; &#125; <br/>&nbsp;&nbsp; function close() &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;gc(ini_get(&#039;session.gc_maxlifetime&#039;)); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // close database-connection <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return @mysql_close($this-&gt;dbHandle); <br/>&nbsp;&nbsp; &#125; <br/>&nbsp;&nbsp; function read($sessID) &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // fetch session-data <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res = mysql_query(&quot;SELECT session_data AS d FROM ws_sessions <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE session_id = &#039;$sessID&#039; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND session_expires &gt; &quot;.time(),$this-&gt;dbHandle); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // return data or an empty string at failure <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($row = mysql_fetch_assoc($res)) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $row&#91;&#039;d&#039;&#93;; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &quot;&quot;; <br/>&nbsp;&nbsp; &#125; <br/>&nbsp;&nbsp; function write($sessID,$sessData) &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // new session-expire-time <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $newExp = time() + $this-&gt;lifeTime; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // is a session with this id in the database? <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res = mysql_query(&quot;SELECT * FROM ws_sessions <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE session_id = &#039;$sessID&#039;&quot;,$this-&gt;dbHandle); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if yes, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(mysql_num_rows($res)) &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...update session-data <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql_query(&quot;UPDATE ws_sessions <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET session_expires = &#039;$newExp&#039;, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session_data = &#039;$sessData&#039; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE session_id = &#039;$sessID&#039;&quot;,$this-&gt;dbHandle); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if something happened, return true <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(mysql_affected_rows($this-&gt;dbHandle)) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if no session-data was found, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // create a new row <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql_query(&quot;INSERT INTO ws_sessions ( <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session_id, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session_expires, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session_data) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VALUES( <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#039;$sessID&#039;, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#039;$newExp&#039;, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#039;$sessData&#039;)&quot;,$this-&gt;dbHandle); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if row was created, return true <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(mysql_affected_rows($this-&gt;dbHandle)) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // an unknown error occured <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false; <br/>&nbsp;&nbsp; &#125; <br/>&nbsp;&nbsp; function destroy($sessID) &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // delete session-data <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql_query(&quot;DELETE FROM ws_sessions WHERE session_id = &#039;$sessID&#039;&quot;,$this-&gt;dbHandle); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if session was deleted, return true, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(mysql_affected_rows($this-&gt;dbHandle)) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...else return false <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false; <br/>&nbsp;&nbsp; &#125; <br/>&nbsp;&nbsp; function gc($sessMaxLifeTime) &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // delete old sessions <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mysql_query(&quot;DELETE FROM ws_sessions WHERE session_expires &lt; &quot;.time(),$this-&gt;dbHandle); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // return affected rows <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return mysql_affected_rows($this-&gt;dbHandle); <br/>&nbsp;&nbsp; &#125; <br/>&#125; <br/>$session = new session(); <br/>session_set_save_handler(array(&amp;$session,&quot;open&quot;), <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array(&amp;$session,&quot;close&quot;), <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array(&amp;$session,&quot;read&quot;), <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array(&amp;$session,&quot;write&quot;), <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array(&amp;$session,&quot;destroy&quot;), <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array(&amp;$session,&quot;gc&quot;)); <br/>session_start(); <br/>// etc... <br/>?&gt;</div><br/><br/>除了上述方法外还有其他办法可以保持Session的同步，可以参考PHP SESSION解惑一文中第四部分“session的同步”。<br/><br/>下面再谈谈Session ID的传递方式：Cookie和URL传递。<br/>Cookie是比较常用的方式，在这种模式下，启动Session后服务器会在HTTP Response中自动加上header(‘Set-Cookie: session_name()=session_id(); path=/’)，并在以后的请求中加上这个Cookie。当从该页跳转到的新页面并调用session_start()后，PHP将检查与给定ID相关联的服务器端存贮的session数据，如果没找到，则新建一个数据集。但是有一点，这种传递方式必须在用户浏览器开启Cookie的情况下才可用，如果万一用户关闭了Cookie，那么只好选择另外一种通过URL参数传递Session ID。<br/>开启URL传递需要在php.ini中设置session.use_trans_sid（文档中提示使用这种方式会有安全风险，因为它显示地将Session ID放在url中，所以除非迫不得已不要选择此方式），并在代码中做如下修改：<br/><br/><div class="code">// 如果客户端使用cookie,可直接传递session到page2.php<br/>echo &#039;&lt;br /&gt;&lt;a href=&quot;page2.php&quot;&gt;page 2&lt;/a&gt;&#039;;<br/> <br/>// 如果客户端禁用cookie<br/>echo &#039;&lt;br /&gt;&lt;a href=&quot;page2.php?&#039; . SID . &#039;&quot;&gt;page 2&lt;/a&gt;&#039;;<br/>/*<br/> 默认php5.2.1下,SID只有在cookie被写入的同时才会有值,如果该session<br/> 对应的cookie已经存在,那么SID将为(未定义)空<br/> */</div><br/><br/>关于Session的内容还有很多，具体可查看官方手册，如果有新的总结会继续更新。<br/><br/>来源：http://imdonkey.com/blog/archives/255
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 写得好，转载：浅谈PHP中的Session机制]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>