带有加密cookies的PHP会话类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带有加密cookies的PHP会话类相关的知识,希望对你有一定的参考价值。

I’ve made this class that can use normal session variables, or cookies. This class can use cookies in two ways: store a single variable in each cookie, or pack many variables, encrypt, and store them into cookies.

Now I always use this class when I have to use session/cookies and when I know that I have not to put too many bytes in cookies (since cookie size is limited).
  1. <?php
  2. /////////////////////////////////////////////////////
  3. // this class was build
  4. // to handle session with cookie or not
  5. // if you choose "zipcook" value the cookies
  6. // are crypted and packed to hide data to malicious
  7. // users.
  8. //
  9. // $use_cookie parameter values:
  10. // no --------> use session
  11. // yes -------> use cookie, one cookie for each variable
  12. // zipcook ---> encrypted cookies
  13. //
  14. // by Giulio Pons, http://www.barattalo.it
  15. //
  16. /////////////////////////////////////////////////////
  17.  
  18. class Session
  19. {
  20. private $use_cookie;
  21. private $preStr;
  22. private $maxCookie;
  23. private $cookieLenght;
  24. private $stringone;
  25. private $duratacookie;
  26. private $secret;
  27.  
  28. public function __construct ($cook = "zipcook") {
  29.  
  30. $this->use_cookie = $cook; //choose mode
  31. $this->preStr= "_KK_"; //prefix for cookies
  32. $this->maxCookie=20; //since cookie lenght is limited, I've limited the number of cookies
  33. $this->cookieLenght=3096; //max cookie length (it depends on browser)
  34. $this->duratacookie=3600*24;//cookie life time
  35. $this->secred="secret"; //secret keyword to crypt/decrypt, change this to customize encryption
  36. if ($this->use_cookie=="yes") {
  37. } elseif ($this->use_cookie=="zipcook") {
  38. $this->stringone = $this->prelevaStringaTotale();
  39. } else {
  40. ini_set("session.gc_maxlifetime","432000");
  41. ini_set("url_rewriter.tags","");
  42. ini_set("session.use_trans_sid", false);
  43. }
  44. }
  45.  
  46. /* ------------------------------------------- */
  47. /* pack variables for parse_str */
  48. /* ------------------------------------------- */
  49. private function build_str($ar) {
  50. $qs = array();
  51. foreach ($ar as $k => $v) { $qs[] = $k.'='.$v; }
  52. return join('&', $qs);
  53. }
  54.  
  55. /* ------------------------------------------- */
  56. /* get the list of variables from the crypted */
  57. /* cookies */
  58. /* ------------------------------------------- */
  59. private function prelevaStringaTotale() {
  60. $cookiesSet = array_keys($_COOKIE);
  61. $out = "";
  62. for ($x=0;$x<count($cookiesSet);$x++) {
  63. if (strpos(" ".$cookiesSet[$x],$this->preStr)==1)
  64. $out.=$_COOKIE[$cookiesSet[$x]];
  65. }
  66. return $this->decrypta($out);
  67. }
  68.  
  69. public function debug() {
  70. // for debug
  71. return $this->prelevaStringaTotale();
  72. }
  73.  
  74. /* ------------------------------------------- */
  75. /* determine available cookies */
  76. /* ------------------------------------------- */
  77. private function calcolaCookieLiberi() {
  78. $cookiesSet = array_keys($_COOKIE);
  79. $c=0;
  80. for ($x=0;$x<count($cookiesSet);$x++) {
  81. if (strpos(" ".$cookiesSet[$x],$this->preStr)==1)
  82. $c+=1;
  83. }
  84. return $this->maxCookie - count($cookiesSet) + $c;
  85. }
  86.  
  87. /* ------------------------------------------- */
  88. /* split the string in blocks to store cookies */
  89. /* ------------------------------------------- */
  90. private function my_str_split($s,$len) {
  91. $output = array();
  92. if (strlen($s)<=$len) {
  93. $output[0] = $s;
  94. return $output;
  95. }
  96. $i = 0;
  97. while (strlen($s)>0) {
  98. $s = substr($s,0,$len);
  99. $output[$i]=$s;
  100. $s = substr($s,$len);
  101. $i++;
  102. }
  103. return $output;
  104. }
  105.  
  106. /* ------------------------------------------- */
  107. /* save vars in cookies or session */
  108. /* ------------------------------------------- */
  109. public function register($var,$value) {
  110. $this->set($var,$value);
  111. }
  112. public function set($var,$value) {
  113. if ($this->use_cookie=="yes") {
  114. setcookie($var,$this->crypta($value),time()+$this->duratacookie,"/", $_SERVER['HTTP_HOST'] );
  115. } elseif ($this->use_cookie=="zipcook") {
  116. if ($this->stringone!="") {
  117. parse_str($this->stringone, $vars);
  118. } else {
  119. $vars=array();
  120. }
  121. $vars[$var] = $value; //aggiungo-modifico valore
  122. $str = $this->crypta($this->build_str($vars));
  123. $arr = $this->my_str_split($str,$this->cookieLenght);
  124. $cLiberi = $this->calcolaCookieLiberi();
  125. if (count($arr) < $cLiberi) {
  126. // c'ho spazio, posso registrare
  127. $this->stringone = $this->build_str($vars);
  128. for ($i=0;$i<count($arr);$i++) {
  129. setcookie($this->preStr.$i,$arr[$i],time()+$this->duratacookie,"/", $_SERVER['HTTP_HOST'] );
  130. }
  131. } else {
  132. //cookie overflow
  133. return "errore cookie overflow";
  134. }
  135. } else {
  136. }
  137. }
  138.  
  139. /* ------------------------------------------- */
  140. /* get variables back from cookies crypted or */
  141. /* not, or directly from session */
  142. /* ------------------------------------------- */
  143. public function get($var) {
  144. if ($this->use_cookie=="yes") {
  145. global $_COOKIE;
  146. return $this->decrypta($_COOKIE[$var]);
  147. } elseif ($this->use_cookie=="zipcook") {
  148. if ($this->stringone!="") {
  149. parse_str($this->stringone, $vars);
  150. } else {
  151. return "";
  152. }
  153. if(!isset($vars[$var])) {
  154. return "";
  155. }
  156. return $vars[$var];
  157. } else {
  158. if ($this->is_registered($var)) {
  159. $this->$var=$GLOBALS[$var];
  160. }
  161. else
  162. if(isset($GLOBALS[$var]))
  163. $this->$var = $GLOBALS[$var];
  164. else
  165. $this->$var="";
  166. return($this->$var);
  167. }
  168. }
  169.  
  170. /* ------------------------------------------- */
  171. /* empty session or cookis */
  172. /* ------------------------------------------- */
  173. public function finish() {
  174. if ($this->use_cookie=="yes") {
  175. $cookiesSet = array_keys($_COOKIE);
  176. for ($x=0;$x<count($cookiesSet);$x++) {
  177. //echo $cookiesSet[$x]."<br/>";
  178. setcookie($cookiesSet[$x],"",time()-3600*24,"/", $_SERVER['HTTP_HOST'] ); //faccio scadere il cookie
  179. }
  180.  
  181. } elseif ($this->use_cookie=="zipcook") {
  182. $cookiesSet = array_keys($_COOKIE);
  183. for ($x=0;$x<count($cookiesSet);$x++) {
  184. if (strpos(" ".$cookiesSet[$x],$this->preStr)==1)
  185. setcookie($cookiesSet[$x],"",time()-3600*24,"/",$_SERVER['HTTP_HOST']);
  186. $this->stringone="";
  187. }
  188. } else {
  189. $_SESSION = array();
  190. }
  191. }
  192.  
  193. /* crypt */
  194. private function crypta($t){
  195. if ($t=="") return $t;
  196. $r = md5(10); $c=0; $v="";
  197. for ($i=0;$i<strlen($t);$i++){
  198. if ($c==strlen($r)) $c=0;
  199. $v.= substr($r,$c,1) . (substr($t,$i,1) ^ substr($r,$c,1));
  200. $c++;
  201. }
  202. return (base64_encode($this->ed($v)));
  203. }
  204. /* decrypt */
  205. private function decrypta($t) {
  206. if ($t=="") return $t;
  207. $t = $this->ed(base64_decode(($t)));
  208. $v = "";
  209. for ($i=0;$i<strlen($t);$i++){
  210. $md5 = substr($t,$i,1);
  211. $i++;
  212. $v.= (substr($t,$i,1) ^ $md5);
  213. }
  214. return $v;
  215. }
  216.  
  217. /* used to crypt/decrypt */
  218. private function ed($t) {
  219. $r = md5($this->secret); $c=0; $v="";
  220. for ($i=0;$i<strlen($t);$i++) {
  221. if ($c==strlen($r)) $c=0;
  222. $v.= substr($t,$i,1) ^ substr($r,$c,1);
  223. $c++;
  224. }
  225. return $v;
  226. }
  227.  
  228.  
  229. }
  230. ?>

以上是关于带有加密cookies的PHP会话类的主要内容,如果未能解决你的问题,请参考以下文章

加密会话(SSL)Cookie 中缺少 Secure 属性 漏洞修复

PHP系列(十三)PHP会话控制

用 Java 解决“加密会话 (ssl) cookie 中缺少安全属性”

PHP 使用cookie或会话的身份验证类

可以使用(加密强)会话 cookie 作为 CSRF 令牌吗?

为啥不使用长寿命会话 ID 来代替带有令牌的持久 cookie?