php 安全過濾函數代碼


php 安全過濾函數代碼,防止用戶惡意輸入內容。

//安全過濾輸入[jb]
function check_str($string, $isurl = false)
{
$string =
preg_replace('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/','',$string);
$string =
str_replace(array("\0","%00","\r"),'',$string);
empty($isurl) &&
$string = preg_replace("/&(?!(#[0-9]+|[a-z]+);)/si",'&',$string);

$string = str_replace(array("%3C",'<'),'<',$string);
$string =
str_replace(array("%3E",'>'),'>',$string);
$string =
str_replace(array('"',"'","\t",' '),array('“','‘',' ',' '),$string);
return
trim($string);
}

/**
* 安全過濾類-過濾javascript,css,iframes,object等不安全參數 過濾級別高
*  Controller中使用方法:$this->controller->fliter_script($value)
* @param  string $value 需要過濾的值
* @return string
*/
function fliter_script($value) {
$value = preg_replace("/(javascript:)?on(click|load|key|mouse|error|abort|move|unload|change|dblclick|move|reset|resize|submit)/i","&111n\\2",$value);
$value = preg_replace("/(.*?)<\/script>/si","",$value);
$value = preg_replace("/(.*?)<\/iframe>/si","",$value);
$value = preg_replace ("//iesU", '', $value);
return $value;
}

/**
* 安全過濾類-過濾HTML標簽
*  Controller中使用方法:$this->controller->fliter_html($value)
* @param  string $value 需要過濾的值
* @return string
*/
function fliter_html($value) {
if (function_exists('htmlspecialchars')) return htmlspecialchars($value);
return str_replace(array("&", '"', "'", "<", ">"), array("&", "\"", "'", "<", ">"), $value);
}

/**
* 安全過濾類-對進入的數據加下划線 防止SQL注入
*  Controller中使用方法:$this->controller->fliter_sql($value)
* @param  string $value 需要過濾的值
* @return string
*/
function fliter_sql($value) {
$sql = array("select", 'insert', "update", "delete", "\'", "\/\*", 
     "\.\.\/", "\.\/", "union", "into", "load_file", "outfile");
$sql_re = array("","","","","","","","","","","","");
return str_replace($sql, $sql_re, $value);
}

/**
* 安全過濾類-通用數據過濾
*  Controller中使用方法:$this->controller->fliter_escape($value)
* @param string $value 需要過濾的變量
* @return string|array
*/
function fliter_escape($value) {
if (is_array($value)) {
  foreach ($value as $k => $v) {
   $value[$k] = self::fliter_str($v);
  }
} else {
  $value = self::fliter_str($value);
}
return $value;
}

/**
* 安全過濾類-字符串過濾 過濾特殊有危害字符
*  Controller中使用方法:$this->controller->fliter_str($value)
* @param  string $value 需要過濾的值
* @return string
*/
function fliter_str($value) {
$badstr = array("\0", "%00", "\r", '&', ' ', '"', "'", "<", ">", "   ", "%3C", "%3E");
$newstr = array('', '', '', '&', ' ', '"', ''', "<", ">", "   ", "<", ">");
$value  = str_replace($badstr, $newstr, $value);
$value  = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $value);
return $value;
}

/**
* 私有路勁安全轉化
*  Controller中使用方法:$this->controller->filter_dir($fileName)
* @param string $fileName
* @return string
*/
function filter_dir($fileName) {
$tmpname = strtolower($fileName);
$temp = array(':/',"\0", "..");
if (str_replace($temp, '', $tmpname) !== $tmpname) {
  return false;
}
return $fileName;
}

/**
* 過濾目錄
*  Controller中使用方法:$this->controller->filter_path($path)
* @param string $path
* @return array
*/
public function filter_path($path) {
$path = str_replace(array("'",'#','=','`','$','%','&',';'), '', $path);
return rtrim(preg_replace('/(\/){2,}|(\\\){1,}/', '/', $path), '/');
}

/**
* 過濾PHP標簽
*  Controller中使用方法:$this->controller->filter_phptag($string)
* @param string $string
* @return string
*/
public function filter_phptag($string) {
return str_replace(array(''), array('<?', '?>'), $string);
}

/**
* 安全過濾類-返回函數
*  Controller中使用方法:$this->controller->str_out($value)
* @param  string $value 需要過濾的值
* @return string
*/
public function str_out($value) {
$badstr = array("<", ">", "%3C", "%3E");
$newstr = array("<", ">", "<", ">");
$value  = str_replace($newstr, $badstr, $value);
return stripslashes($value); //下划線
}

 

php使用正則過濾js腳本代碼實例

 

<?php

 header("Content-type:text/html;charset=utf-8");
 $str = '<script type="text/javascript" src="dd.js"></script>
測試php正則匹配掉js代碼測試php正則匹配掉js代碼測試php正則匹配掉js代碼測試php正則匹配掉js代碼測試php正則匹配掉js代碼測試php正則匹配掉js代碼
<script type="text/javascript" src="123.js"></script>
<script type="text/javascript">
 var aa = "sdsds";
 alert(aa);
</script>
測試php正則匹配掉js代碼';

 $preg = "/<script[\s\S]*?<\/script>/i";
 $newstr = preg_replace($preg,"",$str,3);    //第四個參數中的3表示替換3次,默認是-1,替換全部
 echo $newstr;

?>

 

一個完整成熟的站點,內容過濾,防注入,加密存儲和傳輸,敏感詞屏蔽都是必不可少功能,關於加密傳輸有cookie加密存儲和解密,客戶端js加密到php解密和php文件之間的加密傳輸,涉及的內容較多,如有可能將另開一貼,本貼主要分享一下內容過濾和敏感詞屏蔽的經驗

一,內容過濾

說起過濾,大概馬上會想到addslashes函數,這個常用於防止sql注入,但其實光這些還遠遠不夠,我們要做的常常是將所有不相關的sql關鍵詞全部替換掉,保證發上來的東西放進sql語句里是無法改變sql行為的,所以一般來說,安全起見這兩點要求都需要達到

addslashes函數為了不重復轉義,一般會需要判斷下服務器是否開啟了自動轉義,然后再進行轉義

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function add_slashes( $string , $force = 0)
{
     if (!get_magic_quotes_gpc() || $force )
     {
         if ( is_array ( $string ))
         {
             foreach ( $string as $key => $val )
             {
                 $string [ $key ] = daddslashes( $val , $force );
             }
         }
         else
         {
             $string = addslashes ( $string );
         }
     }
 
     return $string ;
}

 為了讓所有的sql關鍵詞都安全存儲,我們需要將它們轉義,顯示的時候再翻譯回來

  

復制代碼
function sql_encode($str) { if(empty($str)) return ""; $str=trim($str); $str=str_replace("_","\_",$str); $str=str_replace("%","\%",$str); $str=str_replace(chr(39),"&#39;",$str); $str=str_replace("'","''",$str); $str=str_replace("select","sel&#101;ct",$str); $str=str_replace("join","jo&#105;n",$str); $str=str_replace("union","un&#105;on",$str); $str=str_replace("where","wh&#101;re",$str); $str=str_replace("insert","ins&#101;rt",$str); $str=str_replace("delete","del&#101;te",$str); $str=str_replace("update","up&#100;ate",$str); $str=str_replace("like","lik&#101;",$str); $str=str_replace("drop","dro&#112;",$str); $str=str_replace("create","cr&#101;ate",$str); $str=str_replace("modify","mod&#105;fy",$str); $str=str_replace("rename","ren&#097;me",$str); $str=str_replace("alter","alt&#101;r",$str); $str=str_replace("cast","ca&#115;",$str); return $str; }
復制代碼
復制代碼
function sql_decode($str) { if(empty($str)) return ""; $str=str_replace("&#39;",chr(39),$str); $str=str_replace("''","'",$str); $str=str_replace("sel&#101;ct","select",$str); $str=str_replace("jo&#105;n","join",$str); $str=str_replace("un&#105;on","union",$str); $str=str_replace("wh&#101;re","where",$str); $str=str_replace("ins&#101;rt","insert",$str); $str=str_replace("del&#101;te","delete",$str); $str=str_replace("up&#100;ate","update",$str); $str=str_replace("lik&#101;","like",$str); $str=str_replace("dro&#112;","drop",$str); $str=str_replace("cr&#101;ate","create",$str); $str=str_replace("mod&#105;fy","modify",$str); $str=str_replace("ren&#097;me","rename",$str); $str=str_replace("alt&#101;r","alter",$str); $str=str_replace("ca&#115;","cast",$str); return $str; }
復制代碼

  

有了以上的函數,對於sql語句涉及的內容就可以放心使用了,但這還不夠,頁面顯示內容也需要過濾,頁面內容過濾也分很多情況,比如標題是不允許html標簽的,用戶名是除了限制的數字字母,下划線外,其他都不允許使用的,而內容是可以有限制性的使用一些html標簽,這就需要我們針對不同情況做不同的過濾處理

1,標題過濾

復制代碼
function filters_title($text) { $text = trim($text); $text = str_replace("'","",$text); $text = strip_tags($text); $text = stripslashes($text); return $text; }
復制代碼

2,用戶名過濾

復制代碼
function filters_username($string) { $length=strlen($string); if($length<2 || $length>18){return false;} for($n=0; $n<$length; $n++) { $t = ord($string[$n]); if( (47<$t && $t<58) || (64<$t && $t<91) || (96<$t && $t<123) || $t==45 || $t==95 || $t>126){} else{return false;} } return true; }
復制代碼

3,內容過濾

復制代碼
function filters_outcontent($str) { $str = stripslashes($str); $str = preg_replace("/<div[^>]*?>/is","",$str); $str = str_replace("aaaaa","\r\n",$str); $str = str_replace("bbbbb","\n",$str); $str = str_replace("ccccc","\r",$str); $str = str_replace('\"','"',$str); $str = str_replace(array('<HTML', '<BODY', '<INPUT', '<SCRIPT', '<FORM', '<IFRAME'), array('<html', '<body', '<input', '<script', '<form', '<iframe'), $str); $str = str_replace(array('<html', '<body', '<input', '<script', '<form', '<iframe', '<textarea','</textarea>'), array('&lt;html', '&lt;body', '&lt;input', '&lt;script', '&lt;form', '&lt;iframe', '&lt;textarea', '&lt;/textarea&gt;'), $str); return $str; }
復制代碼

可以根據以上思路添加自己的過濾場景,做到符合項目要求

 

二,敏感詞屏蔽

敏感詞屏蔽是現在國內站點必須使用的功能之一了,國情如此,辛辛苦苦做的站,因為這個被封,實在很不划算。根據應用場景,敏感詞過濾可以分為替換和禁止兩種,替換就是不提示,直接替換敏感詞為**等,禁止一半而言需要提示用戶,有敏感詞,需要修改,例如在用戶注冊時候,替換一般用在文章中。

敏感詞需要數據庫支持,將敏感詞存入數據庫時候,可以按照分類,那些是要替換的,那些是要禁止的,按照固定格式存儲,例如 abc=**,這是替換。cba={banned},這是禁止,或者在函數中制定第二個參數,replace或者banned來制定函數執行替換或者精致操作都可以,我采用的是第一種,如果有需要,大家可以根據原函數修改為第二種,最核心的其實很簡單就是個正則查找的過程

復制代碼
function censor($string) { global $dblink, $tablepre; $censoraray = $banned = $banwords = array(); $query = $dblink->query("SELECT * FROM censor WHERE var='censor' "); if($value = $dblink->fetch_array($query)) { $censorstr = is_array($value)?$value['datavalue']:$value; } else { $censorstr = ''; } if (strlen(trim($censorstr)) > 0) { //有值就屏蔽 $censorarr = explode("\n", $censorstr);//按輸入時候的回車分割為數組 foreach($censorarr as $censor) { $censor = trim($censor); if(empty($censor)) continue; list($find, $replace) = explode('=', $censor); $findword = $find; $find = preg_replace("/\\\{(\d+)\\\}/", ".{0,\\1}", preg_quote($find, '/'));//匹配屏蔽語法中的"a{1}s{2}s" switch($replace) { case '{BANNED}': $banwords[] = preg_replace("/\\\{(\d+)\\\}/", "*", preg_quote($findword, '/')); $banned[] = $find; break; default: $censoraray['filter']['find'][] = '/'.$find.'/i'; $censoraray['filter']['replace'][] = $replace; break; } } if($banned) { $censoraray['banned'] = '/('.implode('|', $banned).')/i'; $censoraray['banword'] = implode(', ', $banwords); } if($censoraray['banned'] && preg_match($censoraray['banned'], $string)) { return $censoraray['banned'];//有敏感詞匯不予顯示 } else { $string = empty($censoraray['filter']) ? $string : @preg_replace($censoraray['filter']['find'], $censoraray['filter']['replace'], $string); } } return $string; }
復制代碼

因為我采用了第一種,所以需要將敏感詞從數據庫中取出后,做替換或者禁止的判斷,其實核心代碼很少,算是給大家一些思路吧

 

三,cookie加密

cookie加密存儲是站點安全的很重要選擇步驟,一些敏感的數據存儲在cookie里方便了頁面之間的傳輸,或者用於身份認定,來源判斷,這些數據如果不加密,對有經驗的人來說,很容易就會分析出一些站點的內部機制,或者將cookie用於跨站攻擊。

設置cookie的語法很簡單

setcookie(name,value,expire,path,domain,secure)

name         必需。規定 cookie 的名稱。

value         必需。規定 cookie 的值。

expire         可選。規定 cookie 的有效期。

path         可選。規定 cookie 的服務器路徑。

domain         可選。規定 cookie 的域名。

secure         可選。規定是否通過安全的 HTTPS 連接來傳輸 cookie。

設置cookie的函數可以這樣寫

復制代碼
function set_cookie($var, $value, $life = 0, $prefix = 1) { global $cookiepre, $cookiedomain, $cookiepath, $timestamp, $_SERVER; setcookie(($prefix ? $cookiepre : '').$var, $value, $life ? $timestamp + $life : 0, $cookiepath,$cookiedomain, $_SERVER['SERVER_PORT'] == 443 ? 1 : 0); }
復制代碼

解釋一下

1,$prefix = 1 所以當($prefix ? $cookiepre : '').$var時候就會加上前綴,也可以選擇不加 2,$lift=0 所以當$life ? $timestamp + $life : 0時候,如果傳值了且不是0,就會設置有效期

這里最重要的是加密函數,我這里用的是下面這個

復制代碼
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { $ckey_length = 4; //note 隨機密鑰長度 取值 0-32; //note 加入隨機密鑰,可以令密文無任何規律,即便是原文和密鑰完全相同,加密結果也會每次不同,增大破解難度。 //note 取值越大,密文變動規律越大,密文變化 = 16 的 $ckey_length 次方 //note 當此值為 0 時,則不產生隨機密鑰 $key = md5($key ? $key : UC_KEY); $keya = md5(substr($key, 0, 16)); $keyb = md5(substr($key, 16, 16)); $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : ''; $cryptkey = $keya.md5($keya.$keyc); $key_length = strlen($cryptkey); $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; $string_length = strlen($string); $result = ''; $box = range(0, 255); $rndkey = array(); for($i = 0; $i <= 255; $i++) { $rndkey[$i] = ord($cryptkey[$i % $key_length]); } for($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } for($a = $j = $i = 0; $i < $string_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } if($operation == 'DECODE') { if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) { return substr($result, 26); } else { return ''; } } else { return $keyc.str_replace('=', '', base64_encode($result)); } }
復制代碼

第二個參數可設置為加密encode,或者解密decode。

這樣一來,加密的設置cookie就可以這樣寫

    set_cookie('compound', authcode("$uid\t$uname\t$pw", 'ENCODE', $key));

讀取的時候,將cookie值讀入變量,然后 $cookiearray=explode("\t", authcod($cookieval, 'DECODE', $key))就可以讀入到數組里了。

部分來源:http://www.cnblogs.com/phpinfo/p/3592873.html

 php過濾所有惡意字符:

//php 批量過濾post,get敏感數據
 
if (get_magic_quotes_gpc()) {
 
$_GET = stripslashes_array($_GET);
 
$_POST = stripslashes_array($_POST);
 
}
 
function stripslashes_array(&$array) {
 
while(list($key,$var) = each($array)) {
 
if ($key != 'argc' && $key != 'argv' && (strtoupper($key) != $key || ''.intval($key) == "$key")) {
 
if (is_string($var)) {
 
$array[$key] = stripslashes($var);
 
}
 
if (is_array($var)) {
 
$array[$key] = stripslashes_array($var);
 
}
 
}
 
}
 
return $array;
 
}
 
//過濾
 
function htmlencode($str){
 
if(empty($str)) return;
 
if($str=="") return $str;
 
$str=trim($str);
 
$str=str_replace("&","&",$str);
 
$str=str_replace(">",">",$str);
 
$str=str_replace("<","<",$str);
 
$str=str_replace(chr(32)," ",$str);
 
$str=str_replace(chr(9)," ",$str);
 
$str=str_replace(chr(9)," ",$str);
 
$str=str_replace(chr(34),"&",$str);
 
$str=str_replace(chr(39),"'",$str);
 
$str=str_replace(chr(13),"
 
",$str);
 
$str=str_replace("'","''",$str);
 
$str=str_replace("select","select",$str);
 
$str=str_replace("SCRIPT","SCRIPT",$str);
 
$str=str_replace("script","script",$str);
 
$str=str_replace("join","join",$str);
 
$str=str_replace("union","union",$str);
 
$str=str_replace("where","where",$str);
 
$str=str_replace("insert","insert",$str);
 
$str=str_replace("delete","delete",$str);
 
$str=str_replace("update","update",$str);
 
$str=str_replace("like","like",$str);
 
$str=str_replace("drop","drop",$str);
 
$str=str_replace("create","create",$str);
 
$str=str_replace("modify","modify",$str);
 
$str=str_replace("rename","rename",$str);
 
$str=str_replace("alter","alter",$str);
 
$str=str_replace("cast","cas",$str);
 
return $str;
 
}
 
//解碼
 
function htmldecode($str){
 
if(empty($str)) return;
 
if($str=="") return $str;
 
$str=str_replace("select","select",$str);
 
$str=str_replace("join","join",$str);
 
$str=str_replace("union","union",$str);
 
$str=str_replace("where","where",$str);
 
$str=str_replace("insert","insert",$str);
 
$str=str_replace("delete","delete",$str);
 
$str=str_replace("update","update",$str);
 
$str=str_replace("like","like",$str);
 
$str=str_replace("drop","drop",$str);
 
$str=str_replace("create","create",$str);
 
$str=str_replace("modify","modify",$str);
 
$str=str_replace("rename","rename",$str);
 
$str=str_replace("alter","alter",$str);
 
$str=str_replace("cas","cast",$str);
 
$str=str_replace("&","&",$str);
 
$str=str_replace(">",">",$str);
 
$str=str_replace("<","<",$str);
 
$str=str_replace(" ",chr(32),$str);
 
$str=str_replace(" ",chr(9),$str);
 
$str=str_replace(" ",chr(9),$str);
 
$str=str_replace("&",chr(34),$str);
 
$str=str_replace("'",chr(39),$str);
 
$str=str_replace("
 
",chr(13),$str);
 
$str=str_replace("''","'",$str);
 
return $str;
 
}
 
// 函數:string_filter($string, $match_type=1)
 
// 功能:過濾非法內容
 
// 參數:
 
// $string 需要檢查的字符串
 
// $match_type 匹配類型,1為精確匹配, 2為模糊匹配,默認為1
 
//
 
// 返回:有非法內容返回True,無非法內容返回False
 
// 其他:非法關鍵字列表保存在txt文件里, 分為普通非法關鍵字和嚴重非法關鍵字兩個列表
 
// 作者:heiyeluren
 
// 時間:2006-1-18
 
//
 
//======================================================================
 
function lib_lawless_string_filter($string, $match_type=1)
 
{
 
//字符串空直接返回為非法
 
$string = trim($string);
 
if (empty($string))
 
{
 
return false;
 
 
}
 
//獲取重要關鍵字列表和普通關鍵字列表
 
$common_file = "common_list.txt"; //通用過濾關鍵字列表
 
$signify_file = "signify_list.txt"; //重要過濾關鍵字列表
 
//如果任何列表文件不存在直接返回false,否則把兩個文件列表讀取到兩個數組里
 
if (!file_exists($common_file) || !file_exists($signify_file))
 
{
 
return false;
 
}
 
$common_list = file($common_file);
 
$signify_list = file($signify_file);
 
//精確匹配
 
if ($match_type == 1)
 
{
 
$is_lawless = exact_match($string, $common_list);
 
}
 
//模糊匹配
 
if ($match_type == 2)
 
{
 
$is_lawless = blur_match($string, $common_list, $signify_list);
 
}
 
//判斷檢索結果數組中是否有數據,如果有,證明是非法的
 
if (is_array($is_lawless) && !empty($is_lawless))
 
{
 
return true;
 
}
 
else
 
{
 
return false;
 
}
 
}
 
//---------------------
 
// 精確匹配,為過濾服務
 
//---------------------
 
function exact_match($string, $common_list)
 
{
 
$string = trim($string);
 
$string = lib_replace_end_tag($string);
 
//檢索普通過濾關鍵字列表
 
foreach($common_list as $block)
 
{
 
$block = trim($block);
 
if (preg_match("/^$string$/i", $block))
 
{
 
$blist[] = $block;
 
}
 
}
 
//判斷有沒有過濾內容在數組里
 
if (!empty($blist))
 
{
 
return array_unique($blist);
 
}
 
return false;
 
}
 
//----------------------
 
// 模糊匹配,為過濾服務
 
//----------------------
 
function blur_match($string, $common_list, $signify_list)
 
{
 
$string = trim($string);
 
$s_len = strlen($string);
 
$string = lib_replace_end_tag($string);
 
//檢索普通過濾關鍵字列表
 
foreach($common_list as $block)
 
{
 
$block = trim($block);
 
if (preg_match("/^$string$/i", $block))
 
{
 
$blist[] = $block;
 
}
 
}
 
//檢索嚴重過濾關鍵字列表
 
foreach($signify_list as $block)
 
{
 
$block = trim($block);
 
if ($s_len>=strlen($block) && preg_match("/$block/i", $string))
 
{
 
$blist[] = $block;
 
}
 
}
 
//判斷有沒有過濾內容在數組里
 
if (!empty($blist))
 
{
 
return array_unique($blist);
 
}
 
return false;
 
}
 
//--------------------------
 
// 替換HTML尾標簽,為過濾服務
 
//--------------------------
 
function lib_replace_end_tag($str)
 
{
 
if (empty($str)) return false;
 
$str = htmlspecialchars($str);
 
$str = str_replace( '/', "", $str);
 
$str = str_replace("\\", "", $str);
 
$str = str_replace(">", "", $str);
 
$str = str_replace("<", "", $str);
 
$str = str_replace("", "", $str);
 
$str = str_replace("", "", $str);
 
$str=str_replace("select","select",$str);
 
$str=str_replace("join","join",$str);
 
$str=str_replace("union","union",$str);
 
$str=str_replace("where","where",$str);
 
$str=str_replace("insert","insert",$str);
 
$str=str_replace("delete","delete",$str);
 
$str=str_replace("update","update",$str);
 
$str=str_replace("like","like",$str);
 
$str=str_replace("drop","drop",$str);
 
$str=str_replace("create","create",$str);
 
$str=str_replace("modify","modify",$str);
 
$str=str_replace("rename","rename",$str);
 
$str=str_replace("alter","alter",$str);
 
$str=str_replace("cas","cast",$str);
 
$str=str_replace("&","&",$str);
 
$str=str_replace(">",">",$str);
 
$str=str_replace("<","<",$str);
 
$str=str_replace(" ",chr(32),$str);
 
$str=str_replace(" ",chr(9),$str);
 
$str=str_replace(" ",chr(9),$str);
 
$str=str_replace("&",chr(34),$str);
 
$str=str_replace("'",chr(39),$str);
 
$str=str_replace("
 
",chr(13),$str);
 
$str=str_replace("''","'",$str);
 
$str=str_replace("css","'",$str);
 
$str=str_replace("CSS","'",$str);
 
return $str;
 
//HTML標簽,可以作為擴展過濾
 
/*
 
$tags = array("/html", "/head", "/body", "/div", "/span", "/DOCTYPE", "/title", "/link", "/meta", "/style", "/p", "/h1,", "/h2,", "/h3,", "/h4,", "/h5,", "/h6", "/strong", "/em", "/abbr", "/acronym", "/address", "/bdo", "/blockquote", "/cite", "/q", "/code", "/ins", "/del", "/dfn", "/kbd", "/pre", "/samp", "/var", "/br", "/a", "/img", "/area", "/map", "/object", "/param", "/ul", "/ol", "/li", "/dl", "/dt", "/dd", "/table", "/tr", "/td", "/th", "/tbody", "/thead", "/tfoot", "/col", "/colgroup", "/caption", "/form", "/input", "/textarea", "/select", "/option", "/optgroup", "/button", "/label", "/fieldset", "/legend", "/script", "/noscript", "/b", "/i", "/tt", "/sub", "/sup", "/big", "/small", "/hr" );
 
*/
 
}

 

代碼:

引用是直接這樣:

$xxx = htmlspecialchars($_POST['xxx']);

或者

$xxx = htmlspecialchars($_GET['xxx']);

 

作為PHP程序員,特別是新手,對於互聯網的險惡總是知道的太少,對於外部的入侵有很多時候是素手無策的,他們根本不知道黑客是如何入侵的、提交入侵、上傳漏洞、sql 注入、跨腳本攻擊等等。 

作為最基本的防范你需要注意你的外部提交,做好第一面安全機制處理防火牆。

規則 1:絕不要信任外部數據或輸入
關於Web應用程序安全性,必須認識到的第一件事是不應該信任外部數據。外部數據(outside data) 包括不是由程序員在PHP代碼中直接輸入的任何數據。在采取措施確保安全之前,來自任何其他來源(比如 GET 變量、表單 POST、數據庫、配置文件、會話變量或 cookie)的任何數據都是不可信任的。 例如,下面的數據元素可以被認為是安全的,因為它們是在PHP中設置的。

 代碼如下:
<?php $myUsername = 'tmyer';
$arrayUsers = array('tmyer', 'tom', 'tommy'); define(”GREETING”, 'hello there' . $myUsername); ?>

但是,下面的數據元素都是有瑕疵的。

清單 2. 不安全、有瑕疵的代碼

 代碼如下:
<?php $myUsername = $_POST['username']; //tainted! $arrayUsers = array($myUsername, 'tom', 'tommy'); //tainted! define(”GREETING”, 'hello there' . $myUsername); //tainted! ?>

為 什么第一個變量 $myUsername 是有瑕疵的?因為它直接來自表單 POST。用戶可以在這個輸入域中輸入任何字符串,包括用來清除文件或運行以前上傳的文件的惡意命令。您可能會問,“難道不能使用只接受字母 A-Z 的客戶端(Javascrīpt)表單檢驗腳本來避免這種危險嗎?”是的,這總是一個有好處的步驟,但是正如在后面會看到的,任何人都可以將任何表單下載 到自己的機器上,修改它,然后重新提交他們需要的任何內容。 解決方案很簡單:必須對 $_POST['username'] 運行清理代碼。如果不這么做,那么在使用 $myUsername 的任何其他時候(比如在數組或常量中),就可能污染這些對象。
對用戶輸入進行清理的一個簡單方法是,使用正則表達式來處理它。在這個示例中,只希望接受字母。將字符串限制為特定數量的字符,或者要求所有字母都是小寫的,這可能也是個好主意。
清單 3. 使用戶輸入變得安全

 代碼如下:
<?php $myUsername = cleanInput($_POST['username']); //clean! $arrayUsers = array($myUsername, 'tom', 'tommy'); //clean! define(”GREETING”, 'hello there' . $myUsername); //clean! function cleanInput($input){ $clean = strtolower($input);
$clean = preg_replace(”/[^a-z]/”, “”, $clean); $clean = substr($clean,0,12); return $clean; } ?>

規則 2:禁用那些使安全性難以實施的 PHP 設置 已經知道了不能信任用戶輸入,還應該知道不應該信任機器上配置 PHP 的方式。例如,要確保禁用 register_globals。如果啟用了 register_globals,就可能做一些粗心的事情,比如使用 $variable 替換同名的 GET 或 POST 字符串。通過禁用這個設置,PHP 強迫您在正確的名稱空間中引用正確的變量。要使用來自表單 POST 的變量,應該引用 $_POST['variable']。這樣就不會將這個特定變量誤會成 cookie、會話或 GET 變量。

規則 3:如果不能理解它,就不能保護它
一些開發人員使用奇怪的語法,或者將語句組織得很緊湊,形成簡短但是含義模糊的代碼。這種方式可能效率高,但是如果您不理解代碼正在做什么,那么就無法決定如何保護它。
例如,您喜歡下面兩段代碼中的哪一段?

清單 4. 使代碼容易得到保護

 代碼如下:
<?php //obfuscated code $input = (isset($_POST['username']) ? $_POST['username']:”); //unobfuscated code
$input = ”; if (isset($_POST['username'])){ $input = $_POST['username']; }else{ $input = ”; } ?>

在第二個比較清晰的代碼段中,很容易看出 $input 是有瑕疵的,需要進行清理,然后才能安全地處理。 規則 4:“縱深防御” 是新的法寶 本教程將用示例來說明如何保護在線表單,同時在處理表單的 PHP 代碼中采用必要的措施。同樣,即使使用 PHP regex 來確保 GET 變量完全是數字的,仍然可以采取措施確保 SQL 查詢使用轉義的用戶輸入。
縱深防御不只是一種好思想,它可以確保您不會陷入嚴重的麻煩。 既然已經討論了基本規則,現在就來研究第一種威脅:SQL 注入攻擊。 防止 SQL 注入攻擊 在 SQL 注入攻擊 中,用戶通過操縱表單或 GET 查詢字符串,將信息添加到數據庫查詢中。例如,假設有一個簡單的登錄數據庫。這個數據庫中的每個記錄都有一個用戶名字段和一個密碼字段。構建一個登錄表單,讓用戶能夠登錄。
清單 5. 簡單的登錄表單

 代碼如下:
<html> <head>
<title>Login</title> </head> <body>
<form action=”verify.php” method=”post”> <p><label for='user'>Username</label> <input type='text' name='user' id='user'/> </p> <p><label for='pw'>Password</label> <input type='password' name='pw' id='pw'/> </p> <p><input type='submit' value='login'/></p> </form> </body>
</html>

這個表單接受用戶輸入的用戶名和密碼,並將用戶輸入提交給名為 verify.php 的文件。在這個文件中,PHP 處理來自登錄表單的數據,如下所示:

清單 6. 不安全的 PHP 表單處理代碼

 代碼如下:
<?php $okay = 0; $username = $_POST['user']; $pw = $_POST['pw']; $sql = “select count(*) as ctr from users where username='”.$username.”' and password='”. $pw.”' limit 1″;
$result = mysql_query($sql); while ($data = mysql_fetch_object($result)){ if ($data->ctr == 1){ //they're okay to enter the application! $okay = 1; } } if ($okay){
$_SESSION['loginokay'] = true; header(”index.php”); }else{
header(”login.php”); } ?>

這 段代碼看起來沒問題,對嗎?世界各地成百(甚至成千)的 PHP/MySQL 站點都在使用這樣的代碼。它錯在哪里?好,記住 “不能信任用戶輸入”。這里沒有對來自用戶的任何信息進行轉義,因此使應用程序容易受到攻擊。具體來說,可能會出現任何類型的 SQL 注入攻擊。
例如,如果用戶輸入 foo 作為用戶名,輸入 ' or '1′='1 作為密碼,那么實際上會將以下字符串傳遞給 PHP,然后將查詢傳遞給 MySQL:

 代碼如下:
<?php $sql = “select count(*) as ctr from users where username='foo' and password=” or '1′='1′ limit 1″; ?>

這個查詢總是返回計數值 1,因此 PHP 會允許進行訪問。通過在密碼字符串的末尾注入某些惡意 SQL,黑客就能裝扮成合法的用戶。
解 決這個問題的辦法是,將 PHP 的內置 mysql_real_escape_string() 函數用作任何用戶輸入的包裝器。這個函數對字符串中的字符進行轉義,使字符串不可能傳遞撇號等特殊字符並讓 MySQL 根據特殊字符進行操作。清單 7 展示了帶轉義處理的代碼。

清單 7. 安全的 PHP 表單處理代碼

 代碼如下:
<?php $okay = 0; $username = $_POST['user']; $pw = $_POST['pw']; $sql = “select count(*) as ctr from users where username='”.mysql_real_escape_string($username).”' and password='”. mysql_real_escape_string($pw).”' limit 1″; $result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){ if ($data->ctr == 1){
//they're okay to enter the application! $okay = 1; } } if ($okay){ $_SESSION['loginokay'] = true; header(”index.php”); }else{
header(”login.php”); } ?>

使用 mysql_real_escape_string() 作為用戶輸入的包裝器,就可以避免用戶輸入中的任何惡意 SQL 注入。如果用戶嘗試通過 SQL 注入傳遞畸形的密碼,那么會將以下查詢傳遞給數據庫: select count(*) as ctr from users where username='foo' and password='\' or \'1\'=\'1′ limit 1″
數據庫中沒有任何東西與這樣的密碼匹配。僅僅采用一個簡單的步驟,就堵住了 Web 應用程序中的一個大漏洞。這里得出的經驗是,總是應該對 SQL 查詢的用戶輸入進行轉義。 但是,還有幾個安全漏洞需要堵住。下一項是操縱 GET 變量。 防止用戶操縱 GET 變量
在前一節中,防止了用戶使用畸形的密碼進行登錄。如果您很聰明,應該應用您學到的方法,確保對 SQL 語句的所有用戶輸入進行轉義。 但 是,用戶現在已經安全地登錄了。用戶擁有有效的密碼,並不意味着他將按照規則行事 —— 他有很多機會能夠造成損害。例如,應用程序可能允許用戶查看特殊的內容。所有鏈接指向 template.php?pid=33 或 template.php?pid=321 這樣的位置。URL 中問號后面的部分稱為查詢字符串。因為查詢字符串直接放在 URL 中,所以也稱為 GET 查詢字符串。 在 PHP 中,如果禁用了 register_globals,那么可以用 $_GET['pid'] 訪問這個字符串。在 template.php 頁面中,可能會執行與清單 8 相似的操作。 清單 8. 示例 template.php 

 代碼如下:

<?php $pid = $_GET['pid']; //we create an object of a fictional class Page $obj = new Page; $content = $obj->fetchPage($pid); //and now we have a bunch of PHP that displays the page ?>

這 里有什么錯嗎?首先,這里隱含地相信來自瀏覽器的 GET 變量 pid 是安全的。這會怎么樣呢?大多數用戶沒那么聰明,無法構造出語義攻擊。但是,如果他們注意到瀏覽器的 URL 位置域中的 pid=33,就可能開始搗亂。如果他們輸入另一個數字,那么可能沒問題;但是如果輸入別的東西,比如輸入 SQL 命令或某個文件的名稱(比如 /etc/passwd),或者搞別的惡作劇,比如輸入長達 3,000 個字符的數值,那么會發生什么呢?
在這種情況下,要記住基本規則,不要信任用戶輸入。應用程序開發人員知道 template.php 接受的個人標識符(PID)應該是數字,所以可以使用 PHP 的 is_numeric() 函數確保不接受非數字的 PID,如下所示:

清單 9. 使用 is_numeric() 來限制 GET 變量

 代碼如下:
<?php $pid = $_GET['pid']; if (is_numeric($pid)){ //we create an object of a fictional class Page $obj = new Page; $content = $obj->fetchPage($pid); //and now we have a bunch of PHP that displays the page }else{ //didn't pass the is_numeric() test, do something else! } ?>

這個方法似乎是有效的,但是以下這些輸入都能夠輕松地通過 is_numeric() 的檢查: 100 (有效)
100.1 (不應該有小數位) +0123.45e6 (科學計數法 —— 不好) 0xff33669f (十六進制 —— 危險!危險!)
那么,有安全意識的 PHP 開發人員應該怎么做呢?多年的經驗表明,最好的做法是使用正則表達式來確保整個 GET 變量由數字組成,如下所示:
清單 10. 使用正則表達式限制 GET 變量

 代碼如下:
<?php $pid = $_GET['pid']; if (strlen($pid)){ if (!ereg(”^[0-9]+$”,$pid)){ //do something appropriate, like maybe logging them out or sending them back to home page } }else{
//empty $pid, so send them back to the home page } //we create an object of a fictional class Page, which is now //moderately protected from evil user input $obj = new Page; $content = $obj->fetchPage($pid);
//and now we have a bunch of PHP that displays the page ?>

需 要做的只是使用 strlen() 檢查變量的長度是否非零;如果是,就使用一個全數字正則表達式來確保數據元素是有效的。如果 PID 包含字母、斜線、點號或任何與十六進制相似的內容,那么這個例程捕獲它並將頁面從用戶活動中屏蔽。如果看一下 Page 類幕后的情況,就會看到有安全意識的 PHP 開發人員已經對用戶輸入 $pid 進行了轉義,從而保護了 fetchPage() 方法,如下所示:

清單 11. 對 fetchPage() 方法進行轉義

 代碼如下:
<?php class Page{ function fetchPage($pid){ $sql = “select pid,title,desc,kw,content,status from page where pid='”.mysql_real_escape_string($pid).”'”; } } ?>

您可能會問,“既然已經確保 PID 是數字,那么為什么還要進行轉義?” 因為不知道在多少不同的上下文和情況中會使用 fetchPage() 方法。必須在調用這個方法的所有地方進行保護,而方法中的轉義體現了縱深防御的意義。 如 果用戶嘗試輸入非常長的數值,比如長達 1000 個字符,試圖發起緩沖區溢出攻擊,那么會發生什么呢?下一節更詳細地討論這個問題,但是目前可以添加另一個檢查,確保輸入的 PID 具有正確的長度。您知道數據庫的 pid 字段的最大長度是 5 位,所以可以添加下面的檢查。

清單 12. 使用正則表達式和長度檢查來限制 GET 變量

 代碼如下:
<?php $pid = $_GET['pid']; if (strlen($pid)){ if (!ereg(”^[0-9]+$”,$pid) && strlen($pid) > 5){
//do something appropriate, like maybe logging them out or sending them back to home page } } else { //empty $pid, so send them back to the home page } //we create an object of a fictional class Page, which is now
//even more protected from evil user input $obj = new Page; $content = $obj->fetchPage($pid); //and now we have a bunch of PHP that displays the page ?>

現在,任何人都無法在數據庫應用程序中塞進一個 5,000 位的數值 —— 至少在涉及 GET 字符串的地方不會有這種情況。想像一下黑客在試圖突破您的應用程序而遭到挫折時咬牙切齒的樣子吧!而且因為關閉了錯誤報告,黑客更難進行偵察。 緩沖區溢出攻擊
緩沖區溢出攻擊 試圖使 PHP 應用程序中(或者更精確地說,在 Apache 或底層操作系統中)的內存分配緩沖區發生溢出。請記住,您可能是使用 PHP 這樣的高級語言來編寫 Web 應用程序,但是最終還是要調用 C(在 Apache 的情況下)。與大多數低級語言一樣,C 對於內存分配有嚴格的規則。
緩沖區溢出攻擊向緩沖區發送大量數據,使部分數據溢出到相鄰的內存緩沖區,從而破壞緩沖區或者重寫邏輯。這樣就能夠造成拒絕服務、破壞數據或者在遠程服務器上執行惡意代碼。
防止緩沖區溢出攻擊的惟一方法是檢查所有用戶輸入的長度。例如,如果有一個表單元素要求輸入用戶的名字,那么在這個域上添加值為 40 的 maxlength 屬性,並在后端使用 substr() 進行檢查。清單 13 給出表單和 PHP 代碼的簡短示例。

清單 13. 檢查用戶輸入的長度

 代碼如下:
<?php if ($_POST['submit'] == “go”){
$name = substr($_POST['name'],0,40); } ?> <form action=”<?php echo $_SERVER['PHP_SELF'];?>” method=”post”>
<p><label for=”name”>Name</label> <input type=”text” name=”name” id=”name” size=”20″ maxlength=”40″/></p>
<p><input type=”submit” name=”submit” value=”go”/></p>
</form>

為 什么既提供 maxlength 屬性,又在后端進行 substr() 檢查?因為縱深防御總是好的。瀏覽器防止用戶輸入 PHP 或 MySQL 不能安全地處理的超長字符串(想像一下有人試圖輸入長達 1,000 個字符的名稱),而后端 PHP 檢查會確保沒有人遠程地或者在瀏覽器中操縱表單數據。 正如您看到的,這種方式與前一節中使用 strlen() 檢查 GET 變量 pid 的長度相似。在這個示例中,忽略長度超過 5 位的任何輸入值,但是也可以很容易地將值截短到適當的長度,如下所示:

清單 14. 改變輸入的 GET 變量的長度

 代碼如下:
<?php $pid = $_GET['pid']; if (strlen($pid)){ if (!ereg(”^[0-9]+$”,$pid)){ //if non numeric $pid, send them back to home page } }else{ //empty $pid, so send them back to the home page } //we have a numeric pid, but it may be too long, so let's check if (strlen($pid)>5){ $pid = substr($pid,0,5); }
//we create an object of a fictional class Page, which is now //even more protected from evil user input $obj = new Page; $content = $obj->fetchPage($pid); //and now we have a bunch of PHP that displays the page ?>

注 意,緩沖區溢出攻擊並不限於長的數字串或字母串。也可能會看到長的十六進制字符串(往往看起來像 \xA3 或 \xFF)。記住,任何緩沖區溢出攻擊的目的都是淹沒特定的緩沖區,並將惡意代碼或指令放到下一個緩沖區中,從而破壞數據或執行惡意代碼。對付十六進制緩 沖區溢出最簡單的方法也是不允許輸入超過特定的長度。
如果您處理的是允許在數據庫中輸入較長條目的表單文本區,那么無法在客戶端輕松地限制數據的長度。在數據到達 PHP 之后,可以使用正則表達式清除任何像十六進制的字符串。

清單 15. 防止十六進制字符串

 代碼如下:
<?php if ($_POST['submit'] == “go”){
$name = substr($_POST['name'],0,40); //clean out any potential hexadecimal characters $name = cleanHex($name); //continue processing….
} function cleanHex($input){ $clean = preg_replace(”![\][xX]([A-Fa-f0-9]{1,3})!”, “”,$input); return $clean; }
?> <form action=”<?php echo $_SERVER['PHP_SELF'];?>” method=”post”> <p><label for=”name”>Name</label>
<input type=”text” name=”name” id=”name” size=”20″ maxlength=”40″/></p> <p><input type=”submit” name=”submit” value=”go”/></p> </form>

您 可能會發現這一系列操作有點兒太嚴格了。畢竟,十六進制串有合法的用途,比如輸出外語中的字符。如何部署十六進制 regex 由您自己決定。比較好的策略是,只有在一行中包含過多十六進制串時,或者字符串的字符超過特定數量(比如 128 或 255)時,才刪除十六進制串。
跨站點腳本攻擊 在跨站點腳本(XSS)攻擊中,往往有一個惡意用戶在表單中(或通過其他用戶輸入方式)輸入信息,這些輸入將惡 意的客戶端標記插入過程或數據庫中。例如,假設站點上有一個簡單的來客登記簿程序,讓訪問者能夠留下姓名、電子郵件地址和簡短的消息。惡意用戶可以利用這 個機會插入簡短消息之外的東西,比如對於其他用戶不合適的圖片或將用戶重定向到另一個站點的 Javascrīpt,或者竊取 cookie 信息。
幸運的是,PHP 提供了 strip_tags() 函數,這個函數可以清除任何包圍在 HTML 標記中的內容。strip_tags() 函數還允許提供允許標記的列表,比如 <b> 或 <i>。 瀏覽器內的數據操縱
有一類瀏覽器插件允許用戶篡改頁面上的頭部元素和表單元素。使用 Tamper Data(一個 Mozilla 插件),可以很容易地操縱包含許多隱藏文本字段的簡單表單,從而向 PHP 和 MySQL 發送指令。 用戶在點擊表單上的 Submit 之前,他可以啟動 Tamper Data。在提交表單時,他會看到表單數據字段的列表。Tamper Data 允許用戶篡改這些數據,然后瀏覽器完成表單提交。
讓我們回到前面建立的示例。已經檢查了字符串長度、清除了 HTML 標記並刪除了十六進制字符。但是,添加了一些隱藏的文本字段,如下所示:
清單 17. 隱藏變量

 代碼如下:
<?php if ($_POST['submit'] == “go”){
//strip_tags $name = strip_tags($_POST['name']); $name = substr($name,0,40); //clean out any potential hexadecimal characters
$name = cleanHex($name); //continue processing…. } function cleanHex($input){ $clean = preg_replace(”![\][xX]([A-Fa-f0-9]{1,3})!”, “”,$input); return $clean; } ?> <form action=”<?php echo $_SERVER['PHP_SELF'];?>” method=”post”> <p><label for=”name”>Name</label> <input type=”text” name=”name” id=”name” size=”20″ maxlength=”40″/></p> <input type=”hidden” name=”table” value=”users”/> <input type=”hidden” name=”action” value=”create”/>
<input type=”hidden” name=”status” value=”live\”/>
<p><input type=”submit” name=”submit” value=”go”/></p>
</form>

注意,隱藏變量之一暴露了表名:users。還會看到一個值為 create 的 action 字段。只要有基本的 SQL 經驗,就能夠看出這些命令可能控制着中間件中的一個 SQL 引擎。想搞大破壞的人只需改變表名或提供另一個選項,比如 delete。
現在還剩下什么問題呢?遠程表單提交。 遠程表單提交 Web 的好處是可以分享信息和服務。壞處也是可以分享信息和服務,因為有些人做事毫無顧忌。 以 表單為例。任何人都能夠訪問一個 Web 站點,並使用瀏覽器上的 File > Save As 建立表單的本地副本。然后,他可以修改 action 參數來指向一個完全限定的 URL(不指向 formHandler.php,而是指向 http://www.yoursite.com/formHandler.php,因為表單在這個站點上),做他希望的任何修改,點擊 Submit,服務器會把這個表單數據作為合法通信流接收。 首先可能考慮檢查 $_SERVER['HTTP_REFERER'],從而判斷請求是否來自自己的服務器,這種方法可以擋住大多數惡意用戶,但是擋不住最高明的黑客。這些人足夠聰明,能夠篡改頭部中的引用者信息,使表單的遠程副本看起來像是從您的服務器提交的。
處理遠程表單提交更好的方式是,根據一個惟一的字符串或時間戳生成一個令牌,並將這個令牌放在會話變量和表單中。提交表單之后,檢查兩個令牌是否匹配。如果不匹配,就知道有人試圖從表單的遠程副本發送數據。
要創建隨機的令牌,可以使用 PHP 內置的 md5()、uniqid() 和 rand() 函數,如下所示:

清單 18. 防御遠程表單提交;可限制IP; 

 代碼如下:
<?php session_start(); if ($_POST['submit'] == “go”){ //check token if ($_POST['token'] == $_SESSION['token']){ //strip_tags $name = strip_tags($_POST['name']);
$name = substr($name,0,40); //clean out any potential hexadecimal characters $name = cleanHex($name); //continue processing…. }else{
//stop all processing! remote form posting attempt! } } $token = md5(uniqid(rand(), true)); $_SESSION['token']= $token; function cleanHex($input){ $clean = preg_replace(”![\][xX]([A-Fa-f0-9]{1,3})!”, “”,$input); return $clean; } ?> <form action=”<?php echo $_SERVER['PHP_SELF'];?>” method=”post”> <p><label for=”name”>Name</label> <input type=”text” name=”name” id=”name” size=”20″ maxlength=”40″/></p> <input type=”hidden” name=”token” value=”<?php echo $token;?>”/> <p><input type=”submit” name=”submit” value=”go”/></p> </form>

這種技術是有效的,這是因為在 PHP 中會話數據無法在服務器之間遷移。即使有人獲得了您的 PHP 源代碼,將它轉移到自己的服務器上,並向您的服務器提交信息,您的服務器接收的也只是空的或畸形的會話令牌和原來提供的表單令牌。它們不匹配,遠程表單提交就失敗了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM