index.php ```php granteToken($tokentype); echo $tokenvalue; ?> sss '; echo $name.''; $token_result = $ctoken->checkValidateToken($token,$tokentype); $referer = $_SERVER['HTTP_REFERER']; if(CheckToken::TOKECHECK_EXTERNSUBMIT == $token_result){ //判断是否外部提交 echo '禁止从外部网站提交数据,请检查...'; exit; } elseif(CheckToken::TOKECHECK_DUPLICATESUBMIT == $token_result){ //判断是否重复提交了表单 echo '请不要重复提交,请检查...'; exit; } echo 111; var_dump($_SESSION); ``` token.php ```php session = &$_SESSION; $this->session[CheckToken::SESSION_KEY_TOKEN] = is_array($this->session[CheckToken::SESSION_KEY_TOKEN]) ? $this->session[CheckToken::SESSION_KEY_TOKEN] : array(); $this->session[CheckToken::SESSION_KEY_USEDTOKEN] = is_array($this->session[CheckToken::SESSION_KEY_USEDTOKEN]) ? $this->session[CheckToken::SESSION_KEY_USEDTOKEN] : array(); } /** * 生成一个令牌,并将其放入session和本类对象的缓冲区中 * @actiontype 令牌对象的标识,用于当同一个页面出现多个令牌时,区分不同的令牌时使用,要求每个令牌具有唯一的标识 * @return 生成的令牌 * */ public function granteToken($actiontype) { $token = $this->encrypt($actiontype . ":" . session_id(), CheckToken::ENCRYPT_KEY); $this->setToken($token,$actiontype); return $token; } /** * 检查令牌的特征,判断是否是合法的表单提交 * @$token 待验证的令牌,通常由提交的表单给出 * @actiontype 令牌对象的标识,用于当同一个页面出现多个令牌时,区分不同的令牌时使用,要求每个令牌具有唯一的标识 * @return 令牌验证的结果,其结果定义在本类的常量中,请参考 * */ public function checkValidateToken($token,$actiontype) { if(session_id() != $this->getSessionidFromToken($token)) { return CheckToken::TOKECHECK_EXTERNSUBMIT; } else if (in_array($token,$this->session[CheckToken::SESSION_KEY_USEDTOKEN])) { return CheckToken::TOKECHECK_DUPLICATESUBMIT; } $this->pushToken($token,$actiontype); return CheckToken::TOKECHECK_VALIDATE; } /* * 私有方法,将令牌中附加的sessionid解析出来 * @$token 待验证的令牌 * @return 令牌中附加的sessionid * */ private function getSessionidFromToken($token) { $source = explode(":", $this->decrypt($token, CheckToken::ENCRYPT_KEY)); $sid = $source[1]; return $sid; } /* * 私有方法,将令牌中附加的sessionid解析出来 * @$token 待验证的令牌 * @return 令牌中附加的sessionid * */ private function setToken($token,$actiontype) { $this->session[CheckToken::SESSION_KEY_TOKEN][$actiontype] = $token; $this->token[$actiontype] = $token; } /* * 私有方法,将用过的令牌放入历史缓冲区,可用于判断是否令牌是否被重复使用了 * @$token 待验证的令牌 * @$actiontype 令牌的标识 * */ private function pushToken($token,$actiontype) { array_push($this->session[CheckToken::SESSION_KEY_USEDTOKEN],$token); $this->session[CheckToken::SESSION_KEY_TOKEN][$actiontype] = ""; } /* * 私有方法,令牌的加密算法 * @$txt 待加密的字符串 * @$encrypt_key 加密的密钥 * @return 加密后的字符串 * */ private function keyED($txt, $encrypt_key) { $encrypt_key = md5($encrypt_key); $ctr = 0; $tmp = ""; for ($i = 0; $i < strlen($txt); $i++) { if ($ctr == strlen($encrypt_key)) $ctr = 0; $tmp .= substr($txt, $i, 1) ^ substr($encrypt_key, $ctr, 1); $ctr++; } return $tmp; } /* * 私有方法,对令牌进行加密 * @$txt 待加密的令牌 * @$key 加密的密钥 * @return 加密后得到的令牌 * */ private function encrypt($txt, $key) { $encrypt_key = md5(((float) date("YmdHis") + rand(10000000000000000, 99999999999999999)) . rand(100000, 999999)); $ctr = 0; $tmp = ""; for ($i = 0; $i < strlen($txt); $i++) { if ($ctr == strlen($encrypt_key)) $ctr = 0; $tmp .= substr($encrypt_key, $ctr, 1) . (substr($txt, $i, 1) ^ substr($encrypt_key, $ctr, 1)); $ctr++; } return base64_encode($this->keyED($tmp, $key)); } /* * 私有方法,对令牌进行解密 * @$txt 待解密的令牌 * @$key 加密的密钥 * @return 解密后得到的令牌 * */ private function decrypt($txt, $key) { $txt = $this->keyED(base64_decode($txt), $key); $tmp = ""; for ($i = 0; $i < strlen($txt); $i++) { $md5 = substr($txt, $i, 1); $i++; $tmp .= (substr($txt, $i, 1) ^ $md5); } return $tmp; } } ?> ```